﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using com.lover.astd.common.manager;
using com.lover.astd.common.model;
using com.lover.astd.common.model.building;
using com.lover.astd.common.model.enumer;
using com.lover.common;

namespace com.lover.astd.common.logic
{
    public class MiscMgr : MgrBase
    {
        public MiscMgr() { _logColor = System.Drawing.Color.DarkBlue; }

        #region global
        public bool getServerTime(ProtocolMgr protocol, ILogger logger)
        {
            string url = "/root/server!getServerTime.action";
            com.lover.astd.common.model.ServerResult result = protocol.getXml(url, "获取系统时间");
            if (result == null || !result.CmdSucceed) return false;
            XmlDocument xml = result.CmdResult;
            XmlNode root = xml.SelectSingleNode("/results/time");
            long timeStamp = Int64.Parse(root.InnerText);
            TimeMgr.TimeStamp = timeStamp;
            logger.logDebug(String.Format("got timestamp = {0}", timeStamp));
            return true;
        }
        public bool chooseRole(ProtocolMgr protocol, ILogger logger, string playerId, string code)
        {
            string url = "/root/server!chooseRole.action";
            string data = String.Format("playerId={0}&code={1}", playerId, code);
            com.lover.astd.common.model.ServerResult result = protocol.postXml(url, data, "选择玩家");
            if (result == null || !result.CmdSucceed) return false;
            XmlDocument xml = result.CmdResult;
            logInfo(logger, "选择角色成功");
            return true;
        }
        /// <summary>
        /// 0=success, 1=http failure, 2=您选择的角色不存在, 3=切换角色失败,
        /// 4=角色被封号 , 5= ,10=command error
        /// </summary>
        /// <param name="protocol"></param>
        /// <param name="logger"></param>
        /// <param name="roleName"></param>
        /// <param name="user"></param>
        /// <returns></returns>
        public int getPlayerInfo(ProtocolMgr protocol, ILogger logger, string roleName, User user)
        {
            string url = "/root/server!getPlayerInfoByUserId.action";
            com.lover.astd.common.model.ServerResult result = protocol.getXml(url, "获取玩家信息");
            if (result == null) return 1;
            if(!result.CmdSucceed) return 10;
            XmlDocument xml = result.CmdResult;
            // 首先判断是否需要选择角色
            XmlNode select_role_node = xml.SelectSingleNode("/results/op");
            if (select_role_node != null)
            {
                if (select_role_node.InnerText.Equals("xzjs"))
                {
                    string code = "";
                    XmlNode code_node = xml.SelectSingleNode("/results/code");
                    if (code_node != null) code = code_node.InnerText;
                    XmlNodeList players_node = xml.SelectNodes("/results/player");
                    bool found = false;
                    string playerid = "", playername = "";
                    foreach (XmlNode pnode in players_node)
                    {
                        if (pnode == null || !pnode.HasChildNodes) continue;
                        XmlNodeList childs = pnode.ChildNodes;
                        foreach (XmlNode child in childs)
                        {
                            if (child.Name == "playerid") playerid = child.InnerText;
                            else if (child.Name == "playername") playername = child.InnerText;
                        }
                        if (playername.Equals(roleName))
                        {
                            found = true;
                            break;
                        }
                    }
                    if (!found)
                    {
                        return 2;
                    }
                    if (!chooseRole(protocol, logger, playerid, code))
                    {
                        return 3;
                    }
                    // 继续获取玩家信息
                    result = protocol.getXml(url, "获取玩家信息");
                    if (result == null) return 1;
                    if(!result.CmdSucceed) return 10;
                    xml = result.CmdResult;
                }
            }
            //<results><state>1</state><blockreason>充错服务器转移处理封停</blockreason></results>
            XmlNode block_node = xml.SelectSingleNode("/results/blockreason");
            if (block_node != null)
            {
                logger.logError("角色被封号, 原因是:" + block_node.InnerText);
                return 4;
            }
            XmlNode results = xml.SelectSingleNode("/results/player");
            if (results == null) results = xml.SelectSingleNode("/results/message/player");
            // 首先设置已领过奖励, 因为只有未领过奖励才有这个字段, 就会在refreshPlayerInfo中再次设置
            user.GotLoginReward = true;
            user.clearActivities();
            user.refreshPlayerInfo(results);
            XmlNode updates = xml.SelectSingleNode("/results/playerupdateinfo");
            if (updates == null) updates = xml.SelectSingleNode("/results/message/playerupdateinfo");
            user.refreshPlayerInfo(updates);
            results = xml.SelectSingleNode("/results/limitvalue");
            if (results == null) results = xml.SelectSingleNode("/results/message/limitvalue");
            user.updateLimits(results);

            logInfo(logger, String.Format("{0}({1}级, {2}), {3}年{4}, {5}金币, {6}银币",
                user.Username, user.Level, user.Nation, user.Year, user.SeasonName, user.Gold, user.Silver));

            return 0;
        }
        public void getLoginReward(ProtocolMgr protocol, ILogger logger, User user)
        {
            string url = "/root/mainCity!getPerDayReward.action";
            com.lover.astd.common.model.ServerResult result = protocol.getXml(url, "领取每日奖励");
            if (result == null || !result.CmdSucceed) return;
            XmlDocument xml = result.CmdResult;
            XmlNodeList childs = xml.SelectSingleNode("/results").ChildNodes;
            int gold = 0, token = 0, goldMultiple = 1, tokenMultiple = 1;
            foreach (XmlNode child in childs)
            {
                if (child.Name == "gold") gold = Int32.Parse(child.InnerText);
                else if (child.Name == "token") token = Int32.Parse(child.InnerText);
                else if (child.Name == "goldxs") goldMultiple = Int32.Parse(child.InnerText);
                else if (child.Name == "tokenxs") tokenMultiple = Int32.Parse(child.InnerText);
                else if (child.Name == "playerupdateinfo")
                {
                    XmlNodeList playernodes = child.ChildNodes;
                    foreach (XmlNode node in playernodes)
                    {
                        if (node.Name == "sys_gold") user.Gold = Int32.Parse(node.InnerText);
                        else if (node.Name == "token") user.Token = Int32.Parse(node.InnerText);
                    }
                }
            }
            logInfo(logger, String.Format("领取每日登录奖励, {0}金币, {1}军令", gold, token));
        }
        public void getExtraInfo(ProtocolMgr protocol, ILogger logger, User user)
        {
            string url = "/root/server!getExtraInfo.action";
            com.lover.astd.common.model.ServerResult result = protocol.getXml(url, "获取额外信息");
            if (result == null || !result.CmdSucceed) return;
            XmlDocument xml = result.CmdResult;
            user.removeActivity(ActivityType.RepayEvent);
            XmlNode repayEvent_node = xml.SelectSingleNode("/results/player/isinrepayevent");
            if (repayEvent_node != null)
            {
                if (repayEvent_node.InnerText.ToLower().Equals("true")) user.addActivity(ActivityType.RepayEvent);
            }

            user._can_get_nation_task_reward = false;
            XmlNode nationtask_node = xml.SelectSingleNode("/results/player/nationtaskreward");
            if (nationtask_node != null) user._can_get_nation_task_reward = nationtask_node.InnerText == "1";
        }
        public void getExtraInfo2(ProtocolMgr protocol, ILogger logger, User user)
        {
            string url = "/root/server!getPlayerExtraInfo2.action";
            com.lover.astd.common.model.ServerResult result = protocol.getXml(url, "获取额外信息");
            if (result == null || !result.CmdSucceed) return;
            XmlDocument xml = result.CmdResult;
            XmlNode curMove_node = xml.SelectSingleNode("/results/player/curactive");
            if (curMove_node != null)
            {
                int curmove = -1;
                Int32.TryParse(curMove_node.InnerText, out curmove);
                if (curmove >= 0) user.CurMovable = curmove;
            }
            XmlNode tokencd_node = xml.SelectSingleNode("/results/player/tokencd");
            if (tokencd_node != null)
            {
                int tokencd = 0;
                Int32.TryParse(tokencd_node.InnerText, out tokencd);
                user.TokenCdTime = tokencd;
                if (tokencd == 0) user.TokenCdFlag = false;
            }
            user._is_new_trade = false;
            XmlNode newtrade_node = xml.SelectSingleNode("/results/player/trade200");
            if (newtrade_node != null) user._is_new_trade = newtrade_node.InnerText == "1";
        }
        public void getSessionId(ProtocolMgr protocol, ILogger logger)
        {
            string url = "/root/server!getSessionId.action";
            com.lover.astd.common.model.ServerResult result = protocol.getXml(url, "获取Session信息");
            if (result == null || !result.CmdSucceed) return;
            XmlDocument xml = result.CmdResult;
        }
        #endregion

        #region dinner
        public void getDinnerInfo(ProtocolMgr protocol, ILogger logger, User user)
        {
            string url = "/root/dinner!getAllDinner.action";
            com.lover.astd.common.model.ServerResult result = protocol.getXml(url, "获取宴会信息");
            if (result == null || !result.CmdSucceed) return;
            XmlDocument xml = result.CmdResult;
            XmlNode intime_node = xml.SelectSingleNode("/results/indinnertime");
            if (intime_node != null) user._dinner_in_time = Int32.Parse(intime_node.InnerText);
            else user._dinner_in_time = -1;
            XmlNode state_node = xml.SelectSingleNode("/results/teamstate");
            user._dinner_joined = state_node.InnerText == "1";
            XmlNode dinner = xml.SelectSingleNode("/results/normaldinner");
            // dinner node not exists, means already joined dinner
            if (dinner == null) return;

            user._dinner_count = 0;
            foreach (XmlNode dnode in dinner)
            {
                if (dnode.Name == "num") Int32.TryParse(dnode.InnerText, out user._dinner_count);
            }
            if (user._dinner_count == 0) return;

            XmlNode results = xml.SelectSingleNode("/results");
            if (results == null || !results.HasChildNodes) return;

            user._dinner_team_id = "";
            user._dinner_team_creator = "";

            XmlNodeList team_childs = results.ChildNodes;
            string user_nation = user.Nation;
            foreach (XmlNode tnode in team_childs)
            {
                if (tnode.Name == "team")
                {
                    XmlNodeList tchilds = tnode.ChildNodes;
                    string teamid = "", team_creator = "", nation = ""; int team_num = 0, team_total = 0; ;
                    foreach (XmlNode child in tchilds)
                    {
                        if (child.Name == "teamid") teamid = child.InnerText;
                        else if (child.Name == "creator") team_creator = child.InnerText;
                        else if (child.Name == "nation") nation = child.InnerText;
                        else if (child.Name == "num") team_num = Int32.Parse(child.InnerText);
                        else if (child.Name == "maxnum") team_total = Int32.Parse(child.InnerText);
                    }
                    if (nation.IndexOf(user_nation) < 0 || team_total == team_num) continue;
                    user._dinner_team_id = teamid; user._dinner_team_creator = team_creator;
                    break;
                }
            }
        }
        public void takeDinner(ProtocolMgr protocol, ILogger logger)
        {
            string url = "/root/dinner!preTakeDinner.action";
            string data = "dinnerType=0";
            com.lover.astd.common.model.ServerResult result = protocol.postXml(url, data, "获取预备宴会信息");
            if (result == null || !result.CmdSucceed) return;
            XmlDocument xml = result.CmdResult;

            string url1 = "/root/dinner!takeDinner.action";
            com.lover.astd.common.model.ServerResult result1 = protocol.postXml(url1, data, "获取举办宴会信息");
            if (result1 == null) return;
        }
        public void dismissDinner(ProtocolMgr protocol, ILogger logger)
        {
            string url = "/root/dinner!dismissDinner.action";
            com.lover.astd.common.model.ServerResult result = protocol.getXml(url, "退出宴会");
            if (result == null || !result.CmdSucceed) return;
            XmlDocument xml = result.CmdResult;
            logInfo(logger, "退出宴会成功");
        }
        public void joinDinner(ProtocolMgr protocol, ILogger logger, User user)
        {
            if (user._dinner_team_id == "") return;
            string url = "/root/dinner!joinDinner.action";
            string data = "teamId=" + user._dinner_team_id;
            string desc = String.Format("加入[{0}]的宴会", user._dinner_team_creator);
            com.lover.astd.common.model.ServerResult result = protocol.postXml(url, data, desc);
            if (result == null || !result.CmdSucceed) return;
            XmlDocument xml = result.CmdResult;
            logInfo(logger, desc);
        }
        #endregion

        #region fete
        public int getFeteEventInfo(ProtocolMgr protocol, ILogger logger, User user)
        {
            string url = "/root/fete!getFeteEventInfo.action";
            com.lover.astd.common.model.ServerResult result = protocol.getXml(url, "获取祭祀活动信息");
            if (result == null) return 1;
            if (!result.CmdSucceed) return 2;
            XmlDocument xml = result.CmdResult;

            XmlNodeList god_nodes = xml.SelectNodes("/results/god");
            foreach (XmlNode god_node in god_nodes)
            {
                XmlNode state_node = god_node.SelectSingleNode("state");
                // 0=不能领取, 1=未领取, 2=已领取
                if (state_node.InnerText != "1") continue;
                XmlNode feteId_node = god_node.SelectSingleNode("godticket/id");
                if (feteId_node == null) continue;

                XmlNode ticket_node = god_node.SelectSingleNode("godticket/ticket");
                if (ticket_node == null) continue;

                string feteId = feteId_node.InnerText;
                string tickets = ticket_node.InnerText;
                if (getFeteEventAward(protocol, logger, feteId)) logInfo(logger, String.Format("领取祭祀活动奖励成功, 点券+{0}", tickets));
            }

            return 0;
        }
        public bool getFeteEventAward(ProtocolMgr protocol, ILogger logger, string feteId)
        {
            string url = "/root/fete!recvFeteTicket.action";
            string data = "feteId=" + feteId;
            com.lover.astd.common.model.ServerResult result = protocol.postXml(url, data, "获取祭祀活动奖励信息");
            if (result == null) return false;
            if (!result.CmdSucceed) return false;
            XmlDocument xml = result.CmdResult;
            //<results><state>1</state><godticket><id>1</id><state>2</state><ticket>2500</ticket></godticket></results>
            return true;
        }
        public bool getFeteInfo(ProtocolMgr protocol, ILogger logger, User user)
        {
            string url = "/root/fete.action";
            com.lover.astd.common.model.ServerResult result = protocol.getXml(url, "获取玩家祭祀信息");
            if (result == null || !result.CmdSucceed) return false;
            XmlDocument xml = result.CmdResult;
            XmlNode results = xml.SelectSingleNode("/results/fetelist");
            updateFeteInfo(results, user);
            return true;
        }
        public void doFete(ProtocolMgr protocol, ILogger logger, User user, int feteId)
        {
            string url = "/root/fete!dofete.action";
            com.lover.astd.common.model.ServerResult result = protocol.postXml(url, "feteId=" + feteId, "祭祀");
            if (result == null || !result.CmdSucceed) return;
            XmlDocument xml = result.CmdResult;
            string info = String.Format("祭祀{0}, 花费{1}金币, 获得", user._fete_names[feteId - 1], user._fete_now_gold[feteId - 1]);
            XmlNode results = xml.SelectSingleNode("/results/gains");
            XmlNodeList childs = results.ChildNodes;

            int factor_critical = 0;
            foreach (XmlNode child in childs)
            {
                if (child.Name == "gain")
                {
                    int factor = 1, got = 0; string type = "";
                    XmlNodeList fete_childs = child.ChildNodes;
                    foreach (XmlNode fete_value in fete_childs)
                    {
                        if (fete_value.Name == "pro") factor = Int32.Parse(fete_value.InnerText);
                        else if (fete_value.Name == "addvalue") got = Int32.Parse(fete_value.InnerText);
                        else if (fete_value.Name == "addtype") type = fete_value.InnerText;
                    }
                    if (factor > 1)
                    {
                        info += String.Format("[{0}倍暴击, {1}{2}] ", factor, got, type);
                        if (factor_critical < factor) factor_critical = factor;
                    }
                    else info += String.Format("[{0}{1}]", got, type);
                }
            }
            logInfo(logger, info);
            //if (have_critical && factor_critical >= 10) logSurprise(info);
            XmlNode updateinfo = xml.SelectSingleNode("/results/fetelist");
            if (updateinfo != null) updateFeteInfo(updateinfo, user);
        }
        private void updateFeteInfo(XmlNode list, User user)
        {
            XmlNodeList childs = list.ChildNodes;
            foreach (XmlNode child in childs)
            {
                if (child.Name == "fete")
                {
                    XmlNodeList fete_nodes = child.ChildNodes;
                    int id = 0, gold = 0, freetimes = 0;
                    foreach (XmlNode value_node in fete_nodes)
                    {
                        if (value_node.Name == "id") id = Int32.Parse(value_node.InnerText);
                        else if (value_node.Name == "gold") gold = Int32.Parse(value_node.InnerText);
                        else if (value_node.Name == "freetimes") freetimes = Int32.Parse(value_node.InnerText);
                    }
                    user._fete_now_gold[id - 1] = gold;
                    user._fete_now_free_times[id - 1] = freetimes;
                }
                else if (child.Name == "freeallfete")
                {
                    int count = 0;
                    Int32.TryParse(child.InnerText, out count);
                    user._fete_now_free_times[5] = count;
                }
            }
        }
        #endregion

        #region impose
        /// <summary>
        /// 军资回馈
        /// </summary>
        /// <returns></returns>
        public int getRepayEventInfo(ProtocolMgr protocol, ILogger logger, User user)
        {
            string url = "/root/gift!getRepayEventGiftInfo.action";
            com.lover.astd.common.model.ServerResult result = protocol.getXml(url, "获取军资回馈信息");
            if (result == null) return 1;
            if (!result.CmdSucceed) return 2;
            XmlDocument xml = result.CmdResult;
            XmlNode impose_numnow_node = xml.SelectSingleNode("/results/eventnum");
            if (impose_numnow_node != null) Int32.TryParse(impose_numnow_node.InnerText, out user._impose_repayEvent_numNow);
            else user._impose_repayEvent_numNow = 0;

            XmlNode impose_reward_notgot_node = xml.SelectSingleNode("/results/rewardnum");
            if (impose_reward_notgot_node != null) user._impose_repayEvent_rewardStatus = impose_reward_notgot_node.InnerText;
            else user._impose_repayEvent_rewardStatus = "";

            return 0;
        }
        public void getRepayEventReward(ProtocolMgr protocol, ILogger logger, int id)
        {
            string url = "/root/gift!receiveRepayEventReward.action";
            string data = "id=" + id;
            com.lover.astd.common.model.ServerResult result = protocol.postXml(url, data, "获取军资回馈活动奖励");
            if (result == null) return;
            if (!result.CmdSucceed) return;
            XmlDocument xml = result.CmdResult;
            //<results><state>1</state><message>2024000</message><eventnum>0,0,</eventnum></results>
            XmlNode silver_node = xml.SelectSingleNode("/results/message");
            int silver = 0;
            if (silver_node != null) Int32.TryParse(silver_node.InnerText, out silver);
            logInfo(logger, String.Format("领取军资回馈活动奖励, 银币+{0}", silver));
            return;
        }
        public int getImposeEventInfo(ProtocolMgr protocol, ILogger logger, User user)
        {
            string url = "/root/gift!getEventGiftInfo.action";
            com.lover.astd.common.model.ServerResult result = protocol.getXml(url, "获取征收活动信息");
            if (result == null) return 1;
            if (!result.CmdSucceed) return 2;
            XmlDocument xml = result.CmdResult;
            XmlNode impose_numnow_node = xml.SelectSingleNode("/results/eventnum");
            if (impose_numnow_node != null) Int32.TryParse(impose_numnow_node.InnerText, out user._impose_imposeEvent_numNow);
            else user._impose_imposeEvent_numNow = 0;

            XmlNode impose_reward_notgot_node = xml.SelectSingleNode("/results/rewardnum");
            if (impose_reward_notgot_node != null) user._impose_imposeEvent_rewardStatus = impose_reward_notgot_node.InnerText;
            else user._impose_imposeEvent_rewardStatus = "";

            return 0;
        }
        public void getImposeEventReward(ProtocolMgr protocol, ILogger logger, int id)
        {
            string url = "/root/gift!receiveEventReward.action";
            string data = "id=" + id;
            com.lover.astd.common.model.ServerResult result = protocol.postXml(url, data, "获取征收活动奖励");
            if (result == null) return;
            if (!result.CmdSucceed) return;
            XmlDocument xml = result.CmdResult;
            //<results><state>1</state><message>2024000</message><eventnum>0,0,</eventnum></results>
            XmlNode silver_node = xml.SelectSingleNode("/results/message");
            int silver = 0;
            if (silver_node != null) Int32.TryParse(silver_node.InnerText, out silver);
            logInfo(logger, String.Format("领取征收活动奖励, 银币+{0}", silver));
            return;
        }

        /// <summary>
        /// 获取征收信息
        /// </summary>
        /// <returns></returns>
        public bool getImposeInfo(ProtocolMgr protocol, ILogger logger, User user, int min_loyalty)
        {
            string url = "/root/mainCity!perImpose.action";
            com.lover.astd.common.model.ServerResult result = protocol.getXml(url, "获取玩家征收信息");
            if (result == null || !result.CmdSucceed) return false;
            XmlDocument xml = result.CmdResult;

            tryUseCard(protocol, logger, xml);

            XmlNode results = xml.SelectSingleNode("/results");
            XmlNodeList childs = results.ChildNodes;
            foreach (XmlNode child_element in childs)
            {
                if (child_element.Name == "imposedto")
                {
                    XmlNodeList impose_childs = child_element.ChildNodes;
                    foreach (XmlNode child in impose_childs)
                    {
                        if (child.Name == "loyalty") user._impose_now_loyalty = Int32.Parse(child.InnerText);
                        else if (child.Name == "forceimposecost") user._impose_force_gold = Int32.Parse(child.InnerText);
                        else if (child.Name == "imposenum") user._impose_count = Int32.Parse(child.InnerText);
                        else if (child.Name == "lastimposetime") user._impose_cdtime = Int64.Parse(child.InnerText);
                        else if (child.Name == "cdflag")
                        {
                            if (child.InnerText == "0") user._impose_hasCd = false;
                            else user._impose_hasCd = true;
                        }
                    }
                }
                else if (child_element.Name == "larrydto")
                {
                    string event_name = "";
                    XmlNodeList event_childs = child_element.ChildNodes;
                    foreach (XmlNode e_child in event_childs)
                    {
                        if (e_child.Name == "name") event_name = e_child.InnerText;
                    }
                    if (event_name != "")
                    {
                        string resultinfo = "";
                        resultinfo += String.Format("获得征收事件[{0}] ", event_name);
                        int event_selection = getImposeEvents(event_name, min_loyalty, user._impose_now_loyalty);
                        if (event_selection > 0) resultinfo += answerImposeEvent(protocol, logger, event_selection);
                        logInfo(logger, resultinfo);
                    }
                }

            }
            return true;
        }
        /// <summary>
        /// 征收
        /// </summary>
        /// <param name="force">true为强制征收, 否则为正常征收</param>
        public bool impose(ProtocolMgr protocol, ILogger logger, User user, bool force,  int min_loyalty)
        {
            string url = "/root/mainCity!impose.action";
            if (force) url = "/root/mainCity!forceImpose.action";
            string desc = force ? "强制征收" : "征收";
            com.lover.astd.common.model.ServerResult result = protocol.getXml(url, desc);
            if (result == null || !result.CmdSucceed) return false;
            XmlDocument xml = result.CmdResult;
            XmlNode results = xml.SelectSingleNode("/results");
            XmlNodeList childs = results.ChildNodes;
            string resultinfo = desc + "成功 获得", event_name = "";
            int event_selection = 0;
            bool got_gold = false;
            foreach (XmlNode child in childs)
            {
                if (child.Name == "larrydto") // has event, do event now
                {
                    XmlNodeList event_childs = child.ChildNodes;
                    foreach (XmlNode e_child in event_childs)
                    {
                        if (e_child.Name == "name") event_name = e_child.InnerText;
                    }
                }
                else if (child.Name == "imposenum") user._impose_count = Int32.Parse(child.InnerText);
                else if (child.Name == "imposecd")
                {
                    user._impose_cdtime = Int64.Parse(child.InnerText);
                }
                else if (child.Name == "loyalty") user._impose_now_loyalty = Int32.Parse(child.InnerText);
                else if (child.Name == "copperdis") resultinfo += child.InnerText + "银币 ";
                else if (child.Name == "golddis")
                {
                    if (child.InnerText != "0")
                    {
                        resultinfo += child.InnerText + "金币 ";
                        got_gold = true;
                    }
                }
            }
            if (event_name != "")
            {
                resultinfo += String.Format("获得征收事件[{0}] ", event_name);
                event_selection = getImposeEvents(event_name, min_loyalty, user._impose_now_loyalty);
                if (event_selection > 0) resultinfo += answerImposeEvent(protocol, logger, event_selection);
            }
            resultinfo += String.Format(" 征收CD[{0}] ", formatTime(user._impose_cdtime));
            logInfo(logger, resultinfo);
            if (got_gold) logger.logSurprise(resultinfo);
            return true;
        }
        public string answerImposeEvent(ProtocolMgr protocol, ILogger logger, int optionId)
        {
            string url = "/root/mainCity!selectLE.action";
            com.lover.astd.common.model.ServerResult result = protocol.postXml(url, "opt=" + optionId, "回答征收问题");
            if (result == null || !result.CmdSucceed) return "";
            XmlDocument xml = result.CmdResult;
            string resultinfo = String.Format("回答征收问题, 选择选项[{0}], ", optionId);
            XmlNode results = xml.SelectSingleNode("/results");
            XmlNodeList childs = results.ChildNodes;
            foreach (XmlNode child in childs)
            {
                if (child.Name == "ledto")
                {
                    int loyalty = 0, gold = 0, f = 0, s = 0, silver = 0, t = 0;
                    XmlNodeList nodes = child.ChildNodes;
                    foreach (XmlNode node in nodes)
                    {
                        if (node.Name == "l") loyalty = Int32.Parse(node.InnerText);
                        else if (node.Name == "f") f = Int32.Parse(node.InnerText);
                        else if (node.Name == "s") s = Int32.Parse(node.InnerText);
                        else if (node.Name == "g") gold = Int32.Parse(node.InnerText);
                        else if (node.Name == "c") silver = Int32.Parse(node.InnerText);
                        else if (node.Name == "t") t = Int32.Parse(node.InnerText);
                    }
                    if (loyalty > 0) resultinfo += String.Format("民忠 +{0} ", loyalty);
                    if (gold > 0) resultinfo += String.Format("金币 +{0} ", gold);
                    if (silver > 0) resultinfo += String.Format("银币 +{0} ", silver);
                    if (s > 0) resultinfo += String.Format("威望 +{0} ", s);
                    if (f > 0) resultinfo += String.Format("征收 +{0} ", f);
                    if (t > 0) resultinfo += String.Format("CD -{0} ", t);
                }
            }
            return resultinfo;
        }
        private int getImposeEvents(string name, int min_loyalty, int now_loyalty)
        {
            Dictionary<string, ImposeEvent> events = getAllEvents();
            ImposeEvent ev = null;
            if (events.ContainsKey(name)) ev = events[name];
            if (ev == null) return 0;
            int selection = 0;
            if (now_loyalty > min_loyalty) selection = ev.other_selection;
            else selection = ev.loyalty_selection;
            return selection;
        }
        private Dictionary<string, ImposeEvent> getAllEvents()
        {
            Dictionary<string, ImposeEvent> events = new Dictionary<string, ImposeEvent>();
            //简体的事件
            events.Add("八风暴袭", new ImposeEvent("八风暴袭", "以民为本，赈灾安民[民忠 +7]", "国威为重，押解充军[威望 +Lv*10，CD -10]", 1, 2));
            events.Add("棒打鸳鸯", new ImposeEvent("棒打鸳鸯", "秉公执法，差人劝阻[民忠 +8]", "大局为重，私下调停[银币 +Lv*30]", 1, 2));
            events.Add("不肖子孙", new ImposeEvent("不肖子孙", "姿心所欲，当街暴打[民忠 +4]", "秉公执法，戒律学堂[民忠 +5]", 2, 2));
            events.Add("村南一霸", new ImposeEvent("村南一霸", "秉公执法，差人捉拿[民忠 +5]", "事必躬亲，带队出征[民忠 +7]", 2, 2));
            events.Add("敌国灾民", new ImposeEvent("敌国灾民", "以民为本，安抚收容[民忠 +4]", "国威为重，差人掠夺[银币 +Lv*25]", 1, 2));
            events.Add("敌国逃兵", new ImposeEvent("敌国逃兵", "国威为重，就地正法[威望 +Lv*4]", "大局为重，招安收编[银币 +Lv*25]", 1, 1));
            events.Add("敌国乱民", new ImposeEvent("敌国乱民", "国威为重，临阵诛杀[银币 +Lv*30]", "以民为本，招安收编[民忠 +8]", 2, 1));
            events.Add("敌国伤兵", new ImposeEvent("敌国伤兵", "以民为本，安顿救治[民忠 +7]", "国威为重，就地正法[威望 +Lv*4]", 1, 2));
            events.Add("地牛翻身", new ImposeEvent("地牛翻身", "以民为本，赈灾安民[民忠 +8]", "大局为重，远道求援[银币 +Lv*30]", 1, 2));
            events.Add("独眼石人", new ImposeEvent("独眼石人", "国威为重，差人夺取[威望 +Lv*3]", "以民为本，堂宣明理[民忠 +7]", 2, 1));

            events.Add("恶霸事件", new ImposeEvent("恶霸事件", "升堂传唤[]", "私下调停[]", 1, 1));
            events.Add("风雨飘摇", new ImposeEvent("风雨飘摇", "以民为本，征民修葺[民忠 +5]", "事必躬亲，拆到重建[民忠 +8，银币 -Lv*20]", 2, 2));
            events.Add("风雨祠堂", new ImposeEvent("风雨祠堂", "事必躬亲，修堂祭祖[民忠 +7，金币 +7]", "公务缠身，征民修葺[威望 +Lv*7]", 1, 1));
            events.Add("飞蝗泛滥", new ImposeEvent("飞蝗泛滥", "事必躬亲，食蝗励民[民忠 +5，威望 +Lv,银币 +Lv*10]", "以民为本，设坛祭天[民忠 +4]", 1, 1));
            events.Add("丰收之年", new ImposeEvent("丰收之年", "正常税负[]", "加收税负[]", 1, 1));
            events.Add("官民同庆", new ImposeEvent("官民同庆", "以民为本，开倉放粮[民忠 +8]", "恣心所欲，开怀畅饮[民忠 +5 CD -10]", 1, 2));
            events.Add("孤儿寡母", new ImposeEvent("孤儿寡母", "事必躬亲，躬身询问[民忠 +7]", "公务缠身，差人安抚[威望 +Lv*3]", 1, 2));
            events.Add("荒山沃土", new ImposeEvent("荒山沃土", "事必躬亲，迁寨耕田[民忠 +5，征收 +1]", "公务缠身，征民开荒[征收 +1]", 1, 1));
            events.Add("黄巾军事件", new ImposeEvent("黄巾军事件", "身先士卒[]", "公务缠身[]", 2, 2));
            events.Add("黄巾来犯", new ImposeEvent("黄巾来犯", "事必躬亲，身先士卒[民忠 +7]", "以民为本，招安收编[民忠 +5，银币 +Lv*25]", 1, 2));
            events.Add("黄巾逃兵", new ImposeEvent("黄巾逃兵", "国威为重，就地正法[威望 +Lv*4]", "以民为本，招安收编[民忠 +5]", 2, 1));
            events.Add("黑衣刺客", new ImposeEvent("黑衣刺客", "国威为重，诛其九族[威望 +Lv*7，银币 +Lv*30]", "以民为本，减免税赋[民忠 +8]", 2, 1));

            events.Add("河堤决口", new ImposeEvent("河堤决口", "以民为本，赈灾安民[民忠 +5]", "国威为重，押解充军[银币 +Lv*35]", 1, 2));
            events.Add("虎啸山林", new ImposeEvent("虎啸山林", "事必躬亲，身先士卒[民忠 +5]", "公务缠身[威望 +Lv*3]", 1, 2));
            events.Add("江洋大盗", new ImposeEvent("江洋大盗", "公务缠身，差人捕捉[威望 +Lv*5]", "事必躬亲，身先士卒[民忠 +5]", 2, 1));
            events.Add("井水犯浑", new ImposeEvent("井水犯浑", "以民为本，召集民众[民忠 +5，金币 +5]", "姿心所欲，提水澄清[民忠 +8]", 1, 1));
            events.Add("金枝醉打", new ImposeEvent("金枝醉打", "秉公执法，上前劝阻[民忠 +5]", "大局为重，私下调停[金币 +10]", 2, 2));
            events.Add("路遇逃兵", new ImposeEvent("路遇逃兵", "以民为本，押回大营[民忠 +8]", "国威为重，就地正法[银币 +Lv*15]", 1, 2));
            events.Add("路遇饥民", new ImposeEvent("路遇饥民", "以民为本，赈灾放粮[民忠 +4]", "大局为重，驱往他方[银币 +Lv*10]", 1, 2));
            events.Add("路遇马均", new ImposeEvent("路遇马均", "恣心所欲，盛情款待[民忠 +4，银币 -Lv*10，征收+1]", "礼贤下士，挽留录用[威望 +Lv*2，金币 +10]", 2, 2));
            events.Add("路遇凤姐", new ImposeEvent("路遇凤姐", "礼贤下士，貌相清奇[威望 +Lv]", "姿心所欲，实话实说[征收 +1]", 2, 2));
            events.Add("路遇左慈", new ImposeEvent("路遇左慈", "礼贤下士，下马问安[威望 +Lv*7，银币 +Lv*30，征收+1]", "国威为重，挽留录用[金币 +5，CD -10，征收 +1]", 2, 2));
            events.Add("六月飞雪", new ImposeEvent("六月飞雪", "以民为本，微服私访[民忠 +8]", "国威为重，设坛祭天[威望 +Lv*3]", 1, 2));

            events.Add("蒙面人", new ImposeEvent("蒙面人", "秉公执法，公堂审问[民忠 +7]", "恣心所欲，暗地跟踪[金币 +5]", 2, 2));
            events.Add("魅影妖姬", new ImposeEvent("魅影妖姬", "秉公执法，严刑审问[民忠 +7]", "恣心所欲，法外开恩[金币 +5]", 2, 2));
            events.Add("泥泞古道", new ImposeEvent("泥泞古道", "以民为本，艰难跋涉[民忠 +8]", "国威为重，率民休切[威望 +Lv]", 1, 2));
            events.Add("女飞贼", new ImposeEvent("女飞贼", "严刑审问[]", "法外开恩[]", 1, 1));
            events.Add("清官服", new ImposeEvent("清官服", "礼贤下士，下马接受[威望 +Lv*3]", "恣心所欲，当众穿戴[民忠 +7]", 2, 1));
            events.Add("强抢民女", new ImposeEvent("强抢民女", "秉公执法，押上公堂[民忠 +4]", "大局为重，差人劝阻[银币 +Lv*20]", 1, 2));
            events.Add("欺行霸市", new ImposeEvent("欺行霸市", "秉公执法，升堂传呼[民忠 +4]", "大局为重，私下调停[银币 +Lv*25]", 1, 2));
            events.Add("山贼来袭", new ImposeEvent("山贼来袭", "事必躬亲，身先士卒[民忠 +7]", "公务缠身，派兵镇压[威望 +Lv*3]", 1, 2));
            events.Add("山崩地裂", new ImposeEvent("山崩地裂", "国威为重，率民迁安[威望 +Lv*3]", "以民为本，开倉放粮[民忠 +7，银币 -Lv*20]", 2, 1));
            events.Add("硕鼠硕鼠", new ImposeEvent("硕鼠硕鼠", "公务缠身，差人灭鼠[威望 +Lv*4]", "事必躬亲，抓猫治鼠[民忠 +5，银币 +Lv*5]", 2, 1));
            events.Add("使臣进献", new ImposeEvent("使臣进献", "礼贤下士，宅内宴请[威望 +Lv*2]", "大局为重，公堂静候[银币 +Lv*35]", 1, 1));

            events.Add("铁口仙翁", new ImposeEvent("铁口仙翁", "大局为重，暗中处理[金币 +3]", "秉公执法，公堂审问[民忠 +5，银币 +Lv*10]", 1, 1));
            events.Add("逃兵事件", new ImposeEvent("逃兵事件", "押回营中[]", "就地正法[]", 1, 1));
            events.Add("天雷地火", new ImposeEvent("天雷地火", "事必躬亲，率人救火[民忠 +7]", "公务缠身，呼民自救[银币 +Lv*10]", 1, 2));
            events.Add("台风暴袭", new ImposeEvent("台风暴袭", "赈灾安民[]", "押解充军[]", 1, 1));
            events.Add("瘟疫泛滥", new ImposeEvent("瘟疫泛滥", "以民为本，求医问药[民忠 +6]", "大局为重，隔离疫民[银币 +Lv*30]", 1, 2));
            events.Add("吾国伤兵", new ImposeEvent("吾国伤兵", "以民为本，安顿救治[民忠 +5]", "大局为重，遣散回家[银币 +Lv*15]", 1, 2));
            events.Add("乌线追风", new ImposeEvent("乌线追风", "次心所欲，捉来泡酒[银币 +Lv*30]", "事必躬亲，挥刀斩蛇[民忠 +7]", 2, 1));
            events.Add("五谷丰登", new ImposeEvent("五谷丰登", "以民为本，正常税负[民忠 +4，威望 +Lv*5，征收 +1]", "恣心所欲，加收税负[银币 +Lv*35]", 1, 1));

            events.Add("为民祈雨", new ImposeEvent("为民祈雨", "大局为重，言说明理[民忠 +4，威望 +Lv*2，银币 +Lv*15]", "事必躬亲，设坛祈雨[民忠 +7]", 2, 1));
            events.Add("西域番僧", new ImposeEvent("西域番僧", "恣心所欲，驱散民众[CD -10]", "礼贤下士，旁列静听[金币 +3]", 2, 2));
            events.Add("西域来使", new ImposeEvent("西域来使", "礼贤下士，宅内宴请[民忠 +5]", "国威为重，公堂静候[威望 +Lv*3]", 1, 2));
            events.Add("抓壮丁", new ImposeEvent("抓壮丁", "国威为重，放任不管[威望 +Lv*5，CD -30]", "以民为本，呵诉阻止[民忠 +7]", 2, 1));
            events.Add("珍禽异兽", new ImposeEvent("珍禽异兽", "国威为重，上山围捕[威望 +Lv*7，银币 +Lv*40]", "以民为本，军民勿扰[金币 +10，民忠 +4，征收 +1]", 2, 2));
            events.Add("越狱事件", new ImposeEvent("越狱事件", "同流合污[]", "[]", 1, 1));
            return events;
        }
        private class ImposeEvent
        {
            public string name;
            public string desc1;
            public string desc2;
            public int loyalty_selection;
            public int other_selection;
            public ImposeEvent(string name, string desc1, string desc2, int loyalty_sel, int other_sel)
            {
                this.name = name;
                this.desc1 = desc1;
                this.desc2 = desc2;
                this.loyalty_selection = loyalty_sel;
                this.other_selection = other_sel;
            }
        }
        #endregion

        #region officer
        /// <summary>
        /// 获取官职信息
        /// </summary>
        /// <returns></returns>
        public bool handleOfficerInfo(ProtocolMgr protocol, ILogger logger)
        {
            string url = "/root/officer.action";
            com.lover.astd.common.model.ServerResult result = protocol.getXml(url, "获取玩家官职信息");
            if (result == null || !result.CmdSucceed) return false;
            XmlDocument xml = result.CmdResult;
            XmlNode results = xml.SelectSingleNode("/results");
            XmlNodeList childs = results.ChildNodes;
            foreach (XmlNode child in childs)
            {
                if (child.Name == "savesalary_cd")
                {
                    if (child.InnerText == "0") saveSalary(protocol, logger);
                }
            }
            return true;
        }
        /// <summary>
        /// 领取俸禄
        /// </summary>
        private bool saveSalary(ProtocolMgr protocol, ILogger logger)
        {
            string url = "/root/officer!saveSalary.action";
            com.lover.astd.common.model.ServerResult result = protocol.getXml(url, "领取俸禄");
            if (result == null || !result.CmdSucceed) return false;
            XmlDocument xml = result.CmdResult;
            XmlNode results = xml.SelectSingleNode("/results");
            XmlNodeList childs = results.ChildNodes;
            int money = 0;
            foreach (XmlNode child in childs)
            {
                if (child.Name == "gain") Int32.TryParse(child.InnerText, out money);
            }
            logInfo(logger, String.Format("领取俸禄 [ {0}银币 ]", money));
            return true;
        }
        #endregion

        #region market
        public void getDailyExtraItems(ProtocolMgr protocol, ILogger logger)
        {
            string url = "/root/market!supplementSupperMarket.action";
            com.lover.astd.common.model.ServerResult result = protocol.getXml(url, "获取集市信息");
            if (result == null || !result.CmdSucceed) return;
            //<results><state>1</state><message></message></results>
            logInfo(logger, "使用集市进货令, 增加集市货物");
        }
        /// <summary>
        /// 0=success, 1=no money, 2=other
        /// </summary>
        /// <param name="protocol"></param>
        /// <param name="logger"></param>
        /// <param name="configstr"></param>
        /// <param name="_notbuy_if_fail"></param>
        /// <returns></returns>
        public int handleMarketInfo(ProtocolMgr protocol, ILogger logger, string configstr, bool _notbuy_if_fail,
            int silver_available, int gold_available)
        {
            // parse configuration
            List<MarketConfig> itemConfs = new List<MarketConfig>();
            string[] configs = configstr.Split(',');
            foreach (string config in configs)
            {
                string[] subs = config.Split(':');
                if (subs.Length < 3) continue;
                MarketConfig itemconf = new MarketConfig();
                itemconf.item_type = subs[0];
                int quality = -1;
                if (!Int32.TryParse(subs[1], out quality)) quality = 5;
                itemconf.min_quality = quality;
                itemconf.use_gold = subs[2].ToLower().Equals("true");
                itemConfs.Add(itemconf);
            }

            string url = "/root/market!getPlayerSupperMarket.action";
            com.lover.astd.common.model.ServerResult result = protocol.getXml(url, "获取集市信息");
            if (result == null) return 1;
            if(!result.CmdSucceed) return 2;
            XmlDocument xml = result.CmdResult;
            List<MarketItem> items = new List<MarketItem>();

            bool haveExtraSupply = false;
            XmlNode supply_node = xml.SelectSingleNode("/results/supplementnum");
            if (supply_node != null) haveExtraSupply = supply_node.InnerText != "0";
            if (haveExtraSupply) getDailyExtraItems(protocol, logger);

            XmlNode results = xml.SelectSingleNode("/results");
            XmlNodeList childs = results.ChildNodes;
            foreach (XmlNode child in childs)
            {
                if (child.Name != "suppermarketdto") continue;
                XmlNodeList child_nodes = child.ChildNodes;
                MarketItem item = new MarketItem();
                foreach (XmlNode cnode in child_nodes)
                {
                    if (cnode.Name == "id") item.id = Int32.Parse(cnode.InnerText);
                    else if (cnode.Name == "price")
                    {
                        string[] restr = cnode.InnerText.Split(':');
                        item.restype = restr[1]; item.resnum = Int32.Parse(restr[2]);
                    }
                    else if (cnode.Name == "name") item.itemname = cnode.InnerText;
                    else if (cnode.Name == "num") item.num = Int32.Parse(cnode.InnerText);
                    else if (cnode.Name == "quality") item.quality = Int32.Parse(cnode.InnerText);
                    else if (cnode.Name == "type") item.type = Int32.Parse(cnode.InnerText);
                    else if (cnode.Name == "baoshinum") item.gem_num = Int32.Parse(cnode.InnerText);
                    else if (cnode.Name == "discountnum") item.discount_num = Int32.Parse(cnode.InnerText);
                }
                if (ifBuyItem(item, itemConfs, silver_available, gold_available)) items.Add(item);
            }

            if (items.Count == 0) return 0;
            for (int i = 0, len = items.Count; i < len; i++)
            {
                int dis_result = discountItem(protocol, logger, items[i]);
                if (dis_result == 0)//砍价成功
                {
                    dis_result = discountItem(protocol, logger, items[i]); 
                    if (dis_result == 0) dis_result = discountItem(protocol, logger, items[i]);
                }
                if (_notbuy_if_fail)
                {
                    if (dis_result == 0)
                    {
                        int buy_result = buyItem(protocol, logger, items[i]);
                        if (buy_result > 0) return 2;
                    }
                }
                else
                {
                    int buy_result = buyItem(protocol, logger, items[i]);
                    if (buy_result > 0) return 2;
                }
            }
            return 0;
        }
        private bool ifBuyItem(MarketItem item, List<MarketConfig> itemConfs, int silver_available, int gold_available)
        {
            string[] _red_weapons = new string[] { "彤云角", "红衣将军炮", "化骨丛棘", "弑履岩", "玉麟笙麾", "铜人计里车", "化骨悬灯" };
            string[] _purple_weapons = new string[] { "玄霆角", "无敌将军炮", "五毒问心钉", "七戮锋", "蟠龙华盖", "轩辕指南车", "落魂冥灯" };
            string use_money_type = item.restype;
            string item_type = "";
            if (item.type != 0)
            {
                for (int i = 0, len = _purple_weapons.Length; i < len; i++) if (_purple_weapons[i] == item.itemname) { item_type = "purpleweapon"; break; }
                if (item_type == "") for (int i = 0, len = _red_weapons.Length; i < len; i++) if (_red_weapons[i] == item.itemname) { item_type = "redweapon"; break; }
            }
            else item_type = item.itemname;
            foreach (MarketConfig conf in itemConfs)
            {
                if (conf.item_type.Equals(item_type) && conf.min_quality <= item.quality)
                {
                    if ((use_money_type.Equals("copper") && silver_available >= item.resnum) ||
                        (use_money_type.Equals("gold") && conf.use_gold && gold_available >= item.resnum))
                    {
                        return true;
                    }
                }
            }
            return false;
        }
        /// <summary>
        /// 0=success, 1=http fail, 2=other
        /// </summary>
        /// <param name="protocol"></param>
        /// <param name="logger"></param>
        /// <param name="item"></param>
        private int buyItem(ProtocolMgr protocol, ILogger logger, MarketItem item)
        {
            string url = "/root/market!buySupperMarketCommodity.action";
            string data = "commodityId=" + item.id;
            string desc = String.Format("使用[{0}{1}]购买[{2}{3}]", 
                CommonUtils.getReadable(item.resnum), item.restype_name,
                    item.gem_num > 0 ? item.gem_num : item.num, item.itemname);
            com.lover.astd.common.model.ServerResult result = protocol.postXml(url, data, desc);
            if (result == null) return 1;
            if(!result.CmdSucceed) return 2;
            XmlDocument xml = result.CmdResult;
            // 返回数据简单, 不予解析了
            logInfo(logger, desc);
            return 0;
        }
        /// <summary>
        /// -1=fail, 0=success, 1=http fail, 2=other
        /// </summary>
        /// <param name="protocol"></param>
        /// <param name="logger"></param>
        /// <param name="item"></param>
        /// <returns></returns>
        private int discountItem(ProtocolMgr protocol, ILogger logger, MarketItem item)
        {
            if (item == null) return 0;
            if (item.discount_num == 3) return 0;
            string url = "/root/market!bargainSupperMarketCommodity.action";
            string data = "commodityId=" + item.id;
            string desc = String.Format("对[{0}{1}]=>[{2}{3}]砍价", 
                CommonUtils.getReadable(item.resnum), item.restype_name,
                item.gem_num > 0 ? item.gem_num : item.num, item.itemname);
            com.lover.astd.common.model.ServerResult result = protocol.postXml(url, data, desc);
            if (result == null) return 1;
            if(!result.CmdSucceed) return 2;
            XmlDocument xml = result.CmdResult;
            // 返回数据简单, 不予解析了
            //<results><state>1</state><discount>3</discount><nowprice>7</nowprice></results>
            int discount = 3, nowprice = 0;
            XmlNode discount_node = xml.SelectSingleNode("/results/discount");
            Int32.TryParse(discount_node.InnerText, out discount);
            XmlNode nowprice_node = xml.SelectSingleNode("/results/nowprice");
            Int32.TryParse(nowprice_node.InnerText, out nowprice);
            item.discount_num = discount;
            bool success = item.resnum > nowprice;
            item.resnum = nowprice;
            desc = String.Format("{0}, {1}, 价格变为{2}", desc, success ? "成功" : "失败", CommonUtils.getReadable(nowprice));
            logInfo(logger, desc);

            if (success) return 0;
            else return -1;
        }
        private class MarketConfig
        {
            public string item_type;
            public int min_quality;
            public bool use_gold;
        }
        private class MarketItem
        {
            public int id;
            /// <summary>
            /// copper/gold
            /// </summary>
            public string restype;
            public string restype_name { get { if (restype == "copper") return "银币"; else return "金币"; } }
            public int resnum;
            /// <summary>
            /// 1=白色, 2=蓝色, 3=绿色, 4=黄色, 5=红色
            /// </summary>
            public int quality;
            public int type;
            public int num;
            public string itemname;
            public int gem_num;
            public int discount_num = 3;
        }
        #endregion

        #region stock
        /// <summary>
        /// 0=success, 1=http fail, 2=no money, 3=cd, 10=other
        /// </summary>
        /// <param name="protocol"></param>
        /// <param name="logger"></param>
        /// <param name="configstr"></param>
        /// <param name="user"></param>
        /// <returns></returns>
        public int handleStockInfo(ProtocolMgr protocol, ILogger logger, string configstr, User user)
        {
            int _buy_percent = 70;
            int _sell_percent = 130;
            List<int> _buy_itemids = new List<int>();
            List<StockItem> _items = new List<StockItem>();
            // first parse config
            string[] ids = configstr.Split(',');
            foreach (string idstr in ids)
            {
                if (idstr == "") continue;
                int id = Int32.Parse(idstr);
                if (!_buy_itemids.Contains(id)) _buy_itemids.Add(id);
            }
            int _now_num = 0, _total_num = 0;
            int _stock_cd = -1, _can_trade = -1;

            string url = "/root/stock.action";
            com.lover.astd.common.model.ServerResult result = protocol.getXml(url, "获取贸易信息");
            if (result == null) return 1;
            if(!result.CmdSucceed) return 10;
            XmlDocument xml = result.CmdResult;
            XmlNode results = xml.SelectSingleNode("/results");
            
            XmlNodeList childs = results.ChildNodes;
            foreach (XmlNode child in childs)
            {
                if (child.Name == "currentpositon") _now_num = Int32.Parse(child.InnerText);
                else if (child.Name == "postion") _total_num = Int32.Parse(child.InnerText);
                else if (child.Name == "cd") Int32.TryParse(child.InnerText, out _stock_cd);
                else if (child.Name == "cantrade") Int32.TryParse(child.InnerText, out _can_trade);
                // 绿豆|苹果|木材|铁矿|黄金|珍珠|钻石
                else if (child.Name == "g1" || child.Name == "g2" || child.Name == "g3" ||
                    child.Name == "g4" || child.Name == "g5" || child.Name == "g6" || child.Name == "g7")
                {
                    XmlNodeList cnodes = child.ChildNodes;
                    StockItem item = new StockItem();
                    foreach (XmlNode cnode in cnodes)
                    {
                        if (cnode.Name == "goodid") item.id = Int32.Parse(cnode.InnerText);
                        else if (cnode.Name == "name") item.name = cnode.InnerText;
                        else if (cnode.Name == "price") item.now_price = Int32.Parse(cnode.InnerText);
                        else if (cnode.Name == "originalprice") item.orig_price = Int32.Parse(cnode.InnerText);
                        else if (cnode.Name == "storage") item.storage = Int32.Parse(cnode.InnerText);
                        else if (cnode.Name == "num") item.num_per_buy = Int32.Parse(cnode.InnerText);
                        else if (cnode.Name == "cd") item.cd = Int32.Parse(cnode.InnerText);
                    }
                    _items.Add(item);
                }
            }
            user._stock_cd = _stock_cd;
            if (_stock_cd > 0) return 3;
            if (_can_trade == 0)
            {
                if (_stock_cd > 0) return 3;
                else return 4;
            }

            bool action_done = false;
            foreach (StockItem item in _items)
            {
                if (!_buy_itemids.Contains(item.id)) continue;
                if (item.percent >= _sell_percent)
                {
                    if (item.storage > 0)
                    {
                        sell_buy_item(protocol, logger, true, item.id, item.name, 1, item.num_per_buy, item.now_price * item.num_per_buy);
                        action_done = true;
                        // 卖出cd为买进cd的十分之一
                        user._stock_cd = item.cd * 60 * 1000 / 10;
                    }
                }
                else if (item.percent <= _buy_percent)
                {
                    if (_now_num + item.num_per_buy <= _total_num)
                    {
                        sell_buy_item(protocol, logger, false, item.id, item.name, 1, item.num_per_buy, item.now_price * item.num_per_buy);
                        action_done = true;
                        user._stock_cd = item.cd * 60 * 1000;
                    }
                }
                if (action_done) break;
            }
            if (action_done) return 3;
            return 0;
        }
        private void sell_buy_item(ProtocolMgr protocol, ILogger logger, bool sell, int goodsId, string name, int count, int num_per_sellbuy, int silver_total)
        {
            string url = "/root/stock!tradeStock.action";
            string data = "";
            if (sell) data += "tradeType=1&";
            else data += "tradeType=0&";
            data += "goodId=" + goodsId + "&num=" + count;
            string desc = String.Format("{0}[{1}] * {2}, 银币{3}{4}", sell ? "卖出" : "买入", name, num_per_sellbuy, sell ? "+" : "-", silver_total);
            com.lover.astd.common.model.ServerResult result = protocol.postXml(url, data, desc);
            if (result == null || !result.CmdSucceed) return;
            XmlDocument xml = result.CmdResult;
            // 信息返回非常简单, 没有信息量, 忽略
            logInfo(logger, desc);
        }
        private class StockItem
        {
            public int id;
            public string name;
            public int orig_price;
            public int now_price;
            public int percent { get { if (orig_price > 0) return (int)(100 * now_price / orig_price); else return 0; } }
            public int num_per_buy;
            public int storage;
            public int cd;
        }
        #endregion

        #region stone
        /// <summary>
        /// 0=success, 1=http fail, 2=other
        /// </summary>
        /// <param name="protocol"></param>
        /// <param name="logger"></param>
        /// <param name="gather_percent"></param>
        /// <returns></returns>
        public int handleStoneInfo(ProtocolMgr protocol, ILogger logger, int gather_percent)
        {
            List<StoneQueue> _stone_queues = new List<StoneQueue>();
            string url = "/root/outCity!getPickSpace.action";
            com.lover.astd.common.model.ServerResult result = protocol.getXml(url, "获取玉石采集队列信息");
            if (result == null) return 1;
            if(!result.CmdSucceed) return 2;
            XmlDocument xml = result.CmdResult;
            XmlNode results = xml.SelectSingleNode("/results");
            XmlNodeList childs = results.ChildNodes;
            foreach (XmlNode child in childs)
            {
                if (child.Name == "playerpickdto")
                {
                    XmlNodeList child_nodes = child.ChildNodes;
                    StoneQueue sq = new StoneQueue();
                    foreach (XmlNode cnode in child_nodes)
                    {
                        if (cnode.Name == "id") sq.id = Int32.Parse(cnode.InnerText);
                        else if (cnode.Name == "output") sq.now_stone = Int32.Parse(cnode.InnerText);
                        else if (cnode.Name == "limit") sq.limit_stone = Int32.Parse(cnode.InnerText);
                        else if (cnode.Name == "canendpick") sq.can_gather = cnode.InnerText == "1";
                    }
                    _stone_queues.Add(sq);
                }
            }
            foreach (StoneQueue sq in _stone_queues)
            {
                if (sq.percent >= gather_percent) gatherStone(protocol, logger, sq.id);
            }
            return 0;
        }
        private void gatherStone(ProtocolMgr protocol, ILogger logger, int queueId)
        {
            string url = "/root/outCity!endPick.action";
            string data = "pickSpaceId=" + queueId;
            string desc = String.Format("采集队列 [{0}] 的玉石, ", queueId);
            com.lover.astd.common.model.ServerResult result = protocol.postXml(url, data, desc);
            if (result == null || !result.CmdSucceed) return;
            XmlDocument xml = result.CmdResult;
            XmlNode results = xml.SelectSingleNode("/results");
            XmlNodeList childs = results.ChildNodes;
            int stone_count = 0, gem_count = 0, surplus = 0, critical = 0;
            foreach (XmlNode child in childs)
            {
                if (child.Name == "addbowlder") stone_count = Int32.Parse(child.InnerText);
                else if (child.Name == "baoshinum") gem_count = Int32.Parse(child.InnerText);
                else if (child.Name == "surplus") surplus = Int32.Parse(child.InnerText);
                else if (child.Name == "baoji") critical = Int32.Parse(child.InnerText);
            }
            if (critical != 0) desc += "采集暴击, ";
            desc += String.Format("获得原石 {0} ", stone_count);
            if (surplus > 0) desc += string.Format("余料 {0} ", surplus);
            if (gem_count > 0) desc += String.Format("宝石 {0}", gem_count);
            logInfo(logger, desc);
        }
        public void getStoneMineInfo(ProtocolMgr protocol, ILogger logger, int scopeId)
        {
            string url = "/root/bowlderRes!getBowlderResInfo.action";
            string data = "scopeId=" + scopeId;
            com.lover.astd.common.model.ServerResult result = protocol.postXml(url, data, "获取玉石矿信息");
            if (result == null || !result.CmdSucceed) return;
        }
        private void attackStoneMine(ProtocolMgr protocol, ILogger logger, int scopeId, int mineId)
        {
            string url = "/root/bowlderRes!attackBowlderRes.action";
            string data = String.Format("resId={1}&scopeId={0}", scopeId, mineId);
            com.lover.astd.common.model.ServerResult result = protocol.postXml(url, data, "攻打玉石矿");
            if (result == null || !result.CmdSucceed) return;
        }
        private void rushHarvestStoneMine(ProtocolMgr protocol, ILogger logger, int scopeId, int mineId)
        {
            string url = "/root/bowlderRes!rushHarvestBowlderRes.action";
            string data = String.Format("resId={1}&scopeId={0}", scopeId, mineId);
            com.lover.astd.common.model.ServerResult result = protocol.postXml(url, data, "抢收玉石矿");
            if (result == null || !result.CmdSucceed) return;
        }
        private void cancelStoneMine(ProtocolMgr protocol, ILogger logger, int scopeId, int mineId)
        {
            string url = "/root/bowlderRes!cancelHarvestBowlderRes.action";
            string data = String.Format("resId={1}&scopeId={0}", scopeId, mineId);
            com.lover.astd.common.model.ServerResult result = protocol.postXml(url, data, "放弃玉石矿");
            if (result == null || !result.CmdSucceed) return;
        }
        private class StoneQueue
        {
            public int id;
            public int now_stone;
            public int limit_stone;
            public bool can_gather;
            public int percent { get { if (limit_stone > 0) return (int)(100 * now_stone / limit_stone); else return 0; } }
        }
        #endregion

        #region trade
        /// <summary>
        /// 0=success, 1=http fail, 2=not enough movable, 10=other
        /// </summary>
        /// <param name="protocol"></param>
        /// <param name="logger"></param>
        /// <param name="user"></param>
        /// <param name="visit_merchants"></param>
        /// <param name="max_fail_count"></param>
        /// <param name="silver_available"></param>
        /// <param name="gold_available"></param>
        /// <returns></returns>
        public int handleNewTradeInfo(ProtocolMgr protocol, ILogger logger, User user, string visit_merchants, int max_fail_count,
            int silver_available, int gold_available)
        {
            string url = "/root/caravan!getNewTrade.action";
            com.lover.astd.common.model.ServerResult result = protocol.getXml(url, "获取新通商信息");
            if (result == null) return 1;
            if (!result.CmdSucceed) return 10;
            XmlDocument xml = result.CmdResult;

            XmlNodeList merchant_nodes = xml.SelectNodes("/results/newtrade");
            int[] visit_states = new int[6] { 0, 0, 0, 0, 0, 0 };
            int[] visit_fails = new int[6] { 0, 0, 0, 0, 0, 0 };
            foreach (XmlNode merchant_node in merchant_nodes)
            {
                int id = 0, fail_count = 0, visit_state = 0;
                XmlNodeList childs = merchant_node.ChildNodes;
                foreach (XmlNode child in childs)
                {
                    if (child.Name == "id") id = Int32.Parse(child.InnerText);
                    else if (child.Name == "visitstate") visit_state = Int32.Parse(child.InnerText);
                    else if (child.Name == "visitfailnum") fail_count = Int32.Parse(child.InnerText);
                }
                visit_states[id - 1] = visit_state;
                visit_fails[id - 1] = fail_count;
            }
            for (int i = 0; i < 6; i++)
            {
                if (visit_merchants.Contains((i+1).ToString()))
                {
                    while (visit_states[i] == 0 && visit_fails[i] < max_fail_count && user.CurMovable >= 10)
                    {
                        int v_result = visitNewMerchant(protocol, logger, user, i + 1);
                        if (v_result >= 1) return 10;
                        if (v_result == -1)
                        {
                            visit_fails[i] = visit_fails[i] + 1;
                        }
                        else if (v_result == 0)
                        {
                            visit_states[i] = 1;
                            break;
                        }
                    }
                }
            }
            bool merchant_visit_complete = true;
            for (int i = 0; i < 6; i++)
            {
                if (visit_merchants.Contains((i + 1).ToString()))
                {
                    if (visit_states[i] == 0 && visit_fails[i] < max_fail_count)
                    {
                        // 这里有可能是没有行动力了
                        merchant_visit_complete = false;
                        break;
                    }
                }
            }
            if (!merchant_visit_complete) return 2;
            if (user.CurMovable < 60) return 2;
            int trade_result = doNewTrade(protocol, logger, user);
            if (trade_result > 0) return 10;
            return 0;
        }
        public int doNewTrade(ProtocolMgr protocol, ILogger logger, User user)
        {
            //1=楼兰, 2=西域, 3=巴蜀, 4=大理, 5=闽南, 6=辽东
            string url = "/root/caravan!doNewTrade.action";
            com.lover.astd.common.model.ServerResult result = protocol.getXml(url, "新通商");
            if (result == null) return 1;
            if (!result.CmdSucceed) return 10;
            XmlDocument xml = result.CmdResult;

            int gem_count = 0; int cri = 1;
            XmlNode gem_node = xml.SelectSingleNode("/results/baoshi");
            if (gem_node != null) Int32.TryParse(gem_node.InnerText, out gem_count);

            XmlNode cri_node = xml.SelectSingleNode("/results/cri");
            if (cri_node != null) Int32.TryParse(gem_node.InnerText, out cri);

            string info = String.Format("新版通商成功, 获得宝石+{0}", gem_count);
            logInfo(logger, info);
            return 0;
        }
        /// <summary>
        /// -1=command success but visit failed, 0=command success and visit success
        /// 1 = http fail, 10=other
        /// </summary>
        /// <param name="protocol"></param>
        /// <param name="logger"></param>
        /// <param name="user"></param>
        /// <param name="merchantId"></param>
        /// <returns></returns>
        public int visitNewMerchant(ProtocolMgr protocol, ILogger logger, User user, int merchantId)
        {
            //1=楼兰, 2=西域, 3=巴蜀, 4=大理, 5=闽南, 6=辽东
            string[] names = new string[6] { "楼兰商盟", "西域商盟", "巴蜀商盟", "大理商盟", "闽南商盟", "辽东商盟" };
            string url = "/root/caravan!newTradeVisit.action";
            string data = "caravanId=" + merchantId;
            com.lover.astd.common.model.ServerResult result = protocol.postXml(url, data, "拜访商盟");
            if (result == null) return 1;
            if (!result.CmdSucceed) return 10;
            XmlDocument xml = result.CmdResult;
            XmlNode succ_node = xml.SelectSingleNode("/results/succ");
            if (succ_node != null)
            {
                if (succ_node.InnerText == "1")
                {
                    logInfo(logger, String.Format("拜访[{0}]成功了, 天灵灵地灵灵~~", names[merchantId-1]));
                    return 0;
                }
                else
                {
                    logInfo(logger, String.Format("拜访[{0}]失败了?? 您比习老板还忙啊?!!", names[merchantId - 1]));
                    return -1;
                }
            }

            return -1;
        }
        /// <summary>
        /// 0=success, 1=http failure, 2=work done, 3=not enough movable, 10=other
        /// </summary>
        /// <param name="protocol"></param>
        /// <param name="logger"></param>
        /// <param name="user"></param>
        /// <param name="do_tired_trade"></param>
        /// <returns></returns>
        public int handleTradeInfo(ProtocolMgr protocol, ILogger logger, User user, out int state, bool do_tired_trade = false, bool only_free=true)
        {
            state = 0;
            if (user.Level < 40) return 10;
            Building build = ServiceFactory.getBuildingManager().getBuilding(user._buildings, "驿站");
            if (build != null)
            {
                if (build.Level >= 200)
                {
                    user._is_new_trade = true;
                    return 2;
                }
            } 
            List<string> _merchant_db = getMerchants();
            List<TradeMerchant> _event_1_silver = new List<TradeMerchant>();
            List<TradeMerchant> _event_1_stone = new List<TradeMerchant>();
            List<TradeMerchant> _event_1_gem = new List<TradeMerchant>();
            List<TradeMerchant> _event_2_silver = new List<TradeMerchant>();
            List<TradeMerchant> _event_2_stone = new List<TradeMerchant>();
            List<TradeMerchant> _event_2_gem = new List<TradeMerchant>();

            List<TradeMerchant> _refresh_merchants = new List<TradeMerchant>();
            List<TradeMerchant> _recent_merchants = new List<TradeMerchant>();

            int _trade_free_times = 0;
            int _trade_cost1 = 0, _trade_cost2 = 0, _trade_state = 0, _trade_remainHigh = 0;
            int _trade_card_num = 0;

            string url = "/root/caravan!getTradeInfo.action";
            com.lover.astd.common.model.ServerResult result = protocol.getXml(url, "获取通商信息");
            if (result == null) return 1;
            if(!result.CmdSucceed) return 10;
            XmlDocument xml = result.CmdResult;

            #region get info
            XmlNode cost1_node = xml.SelectSingleNode("/results/cost1");
            if (cost1_node != null) Int32.TryParse(cost1_node.InnerText, out _trade_cost1);
            XmlNode cost2_node = xml.SelectSingleNode("/results/cost2");
            if (cost2_node != null) Int32.TryParse(cost2_node.InnerText, out _trade_cost2);
            XmlNode status_node = xml.SelectSingleNode("/results/status");
            if (status_node != null) Int32.TryParse(status_node.InnerText, out _trade_state);
            XmlNode remainhigh_node = xml.SelectSingleNode("/results/remainhigh");
            if (remainhigh_node != null) Int32.TryParse(remainhigh_node.InnerText, out _trade_remainHigh);

            XmlNodeList card_nodes = xml.SelectNodes("/results/card");
            if (card_nodes != null)
            {
                foreach (XmlNode card_node in card_nodes)
                {
                    if (card_node == null || !card_node.HasChildNodes) continue;
                    XmlNode cardnum_node = card_node.SelectSingleNode("cardnum");
                    if (cardnum_node != null) Int32.TryParse(cardnum_node.InnerText, out _trade_card_num);
                }
            }

            XmlNode results = xml.SelectSingleNode("/results");
            XmlNodeList childs = results.ChildNodes;
            foreach (XmlNode child in childs)
            {
                if (child.Name == "tradetimes") _trade_free_times = Int32.Parse(child.InnerText);
                else if (child.Name == "tradecombodto")
                {
                    XmlNodeList event_list = child.ChildNodes;
                    int etype = 0; string event_merchant_strs = "";
                    foreach (XmlNode enode in event_list)
                    {
                        if (enode.Name == "type") etype = Int32.Parse(enode.InnerText);
                        else if (enode.Name == "info") event_merchant_strs = enode.InnerText;
                    }
                    //大理商人+荆楚商人,浔阳商人+大理商人,辽东商人+巴蜀商人:4+9,11+4,6+3:dali+jinchu,xunyang+dali,liaodong+bashu
                    event_merchant_strs = event_merchant_strs.Substring(0, event_merchant_strs.IndexOf(":"));
                    string[] event_merchant_groups = event_merchant_strs.Split(',');
                    if (etype == 1)
                    {
                        if (event_merchant_groups.Length > 0 && event_merchant_groups[0] != "")
                        {
                            string[] merchant_names = event_merchant_groups[0].Split('+');
                            foreach (string name in merchant_names)
                            {
                                TradeMerchant mer = new TradeMerchant();
                                mer.name = name;
                                mer.id = _merchant_db.IndexOf(name) + 1;
                                _event_1_silver.Add(mer);
                            }
                        }
                        if (event_merchant_groups.Length > 1 && event_merchant_groups[1] != "")
                        {
                            string[] merchant_names = event_merchant_groups[1].Split('+');
                            foreach (string name in merchant_names)
                            {
                                TradeMerchant mer = new TradeMerchant();
                                mer.name = name;
                                mer.id = _merchant_db.IndexOf(name) + 1;
                                _event_1_stone.Add(mer);
                            }
                        }
                        if (event_merchant_groups.Length > 2 && event_merchant_groups[2] != "")
                        {
                            string[] merchant_names = event_merchant_groups[2].Split('+');
                            foreach (string name in merchant_names)
                            {
                                TradeMerchant mer = new TradeMerchant();
                                mer.name = name;
                                mer.id = _merchant_db.IndexOf(name) + 1;
                                _event_1_gem.Add(mer);
                            }
                        }
                    }
                    else if (etype == 2)
                    {
                        if (event_merchant_groups.Length > 0 && event_merchant_groups[0] != "")
                        {
                            string[] merchant_names = event_merchant_groups[0].Split('+');
                            foreach (string name in merchant_names)
                            {
                                TradeMerchant mer = new TradeMerchant();
                                mer.name = name;
                                mer.id = _merchant_db.IndexOf(name) + 1;
                                _event_2_silver.Add(mer);
                            }
                        }
                        if (event_merchant_groups.Length > 1 && event_merchant_groups[1] != "")
                        {
                            string[] merchant_names = event_merchant_groups[1].Split('+');
                            foreach (string name in merchant_names)
                            {
                                TradeMerchant mer = new TradeMerchant();
                                mer.name = name;
                                mer.id = _merchant_db.IndexOf(name) + 1;
                                _event_2_stone.Add(mer);
                            }
                        }
                        if (event_merchant_groups.Length > 2 && event_merchant_groups[2] != "")
                        {
                            string[] merchant_names = event_merchant_groups[2].Split('+');
                            foreach (string name in merchant_names)
                            {
                                TradeMerchant mer = new TradeMerchant();
                                mer.name = name;
                                mer.id = _merchant_db.IndexOf(name) + 1;
                                _event_2_gem.Add(mer);
                            }
                        }
                    }
                }
                else if (child.Name == "refresh")
                {
                    XmlNodeList refresh_childs = child.ChildNodes;
                    TradeMerchant merchant = new TradeMerchant();
                    foreach (XmlNode rchild in refresh_childs)
                    {
                        if (rchild.Name == "textilemerchantid") merchant.id = Int32.Parse(rchild.InnerText);
                        else if (rchild.Name == "name") merchant.name = rchild.InnerText;
                        else if (rchild.Name == "state") merchant.discovered = rchild.InnerText == "2";
                    }
                    _refresh_merchants.Add(merchant);
                }
                else if (child.Name == "recent")
                {
                    XmlNodeList recent_childs = child.ChildNodes;
                    TradeMerchant merchant = new TradeMerchant();
                    foreach (XmlNode rchild in recent_childs)
                    {
                        if (rchild.Name == "textilemerchantid") merchant.id = Int32.Parse(rchild.InnerText);
                        else if (rchild.Name == "name") merchant.name = rchild.InnerText;
                    }
                    _recent_merchants.Add(merchant);
                }
            }
            #endregion

            state = _trade_state;
            if (_trade_state == 3) return 2;
            // start do things
            bool usecard = _trade_card_num > 0;
            int merchantId = 0;
            bool card_used = false;
            // 首先看有无免费次数, 有的话直接用掉
            if (_trade_free_times > 0) logInfo(logger, "发现免费通商, 开启通商");
            if (_trade_free_times == 0)
            {
                if (only_free) return 0;
                if (!do_tired_trade && _trade_state != 1) return 2;
                if (_trade_state == 1 && user.CurMovable < _trade_cost1) return 3;
                if (_trade_state == 2 && user.CurMovable < _trade_cost2) return 3;
            }

            // do things
            merchantId = getMerchantToTrade(usecard, out card_used, _event_1_silver, _event_1_stone, _event_1_gem,
                _event_2_silver, _event_2_stone, _event_2_gem, _refresh_merchants, _recent_merchants);
            if (merchantId == 0) return 10;
            trade(protocol, logger, merchantId, _merchant_db[merchantId - 1], card_used);
            return 0;
        }
        private void trade(ProtocolMgr protocol, ILogger logger, int merchantId, string name, bool useCard)
        {
            string url = "/root/caravan!trade.action";
            string data = "caravanId=" + merchantId;
            if (useCard) data += "&usecard=1";
            string desc = String.Format("{0}通商[{1}]", useCard ? "使用[商人召唤卡]," : "", name);
            com.lover.astd.common.model.ServerResult result = protocol.postXml(url, data, desc);
            if (result == null || !result.CmdSucceed) return;
            XmlDocument xml = result.CmdResult;
            XmlNode silver_node = xml.SelectSingleNode("/results/gold");
            if (silver_node != null)
            {
                desc += String.Format(", 银币+{0}", silver_node.InnerText);
            }
            XmlNode silvercombo_node = xml.SelectSingleNode("/results/goldcombo");
            if (silvercombo_node != null)
            {
                desc += String.Format(", 完成银币事件, 获得{0}银币", silvercombo_node.InnerText);
            }
            XmlNode gemcombo_node = xml.SelectSingleNode("/results/jewelcombo");
            if (gemcombo_node != null)
            {
                //XmlNode comboid_node = xml.SelectSingleNode("/results/comboid");
                //if (comboid_node != null)
                //{
                //    int comboid = 0;
                //    if (Int32.TryParse(comboid_node.InnerText, out comboid))
                //    {
                //        desc += String.Format("");
                //    }
                //}
                desc += String.Format(", 完成宝石事件, 获得宝石{0}个", gemcombo_node.InnerText);
            }
            XmlNode stonecombo_node = xml.SelectSingleNode("/results/bowldercombo");
            if (stonecombo_node != null)
            {
                desc += String.Format(", 完成玉石事件, 获得玉石{0}个", stonecombo_node.InnerText);
            }
            logInfo(logger, desc);
        }
        private int getMerchantToTrade(bool usecard, out bool card_used, List<TradeMerchant> _event_1_silver,List<TradeMerchant> _event_1_stone,
            List<TradeMerchant> _event_1_gem, List<TradeMerchant> _event_2_silver, 
            List<TradeMerchant> _event_2_stone, List<TradeMerchant> _event_2_gem,
            List<TradeMerchant> _refresh_merchants, List<TradeMerchant> _recent_merchants)
        {
            card_used = false;
            // 首先查看是否马上就要完成事件, 如果是, 那么完成事件, 否则, 查看是否还未结识, 
            // 如果有未结识的, 开启, 如果都结识了, 开始按照宝石>银币>玉石, 2星>1星, 来开启
            if (_event_2_gem.Count > 0)
            {
                if (_recent_merchants.Count > 0)
                {
                    if (_recent_merchants.Count == 1) // 最近商人只有一位
                    {
                        if (_event_2_gem[0].id == _recent_merchants[0].id) // 事件2中第一位商人和最近商人匹配
                        {
                            // 查找是否有事件中下一个商人
                            int mid = 0;
                            foreach (TradeMerchant m in _refresh_merchants)
                            {
                                if (m.id == _event_2_gem[1].id) { mid = m.id; break; }
                            }
                            if (mid > 0) return mid;
                        }
                    }
                    else if (_recent_merchants.Count >= 2) // 最近商人数>=2
                    {
                        // 如果事件2中前2位都匹配
                        if (_event_2_gem[0].id == _recent_merchants[_recent_merchants.Count - 2].id &&
                            _event_2_gem[1].id == _recent_merchants[_recent_merchants.Count - 1].id)
                        {
                            // 查找是否有事件中下一个商人
                            int mid = 0;
                            foreach (TradeMerchant m in _refresh_merchants)
                            {
                                if (m.id == _event_2_gem[2].id) { mid = m.id; break; }
                            }
                            if (mid > 0) return mid;
                            else if (usecard)
                            {
                                card_used = true; return _event_2_gem[2].id;
                            }
                        }
                        else if (_event_2_gem[0].id == _recent_merchants[_recent_merchants.Count - 1].id) // 事件2中第一位商人和最近商人匹配
                        {
                            // 查找是否有事件中下一个商人
                            int mid = 0;
                            foreach (TradeMerchant m in _refresh_merchants)
                            {
                                if (m.id == _event_2_gem[1].id) { mid = m.id; break; }
                            }
                            if (mid > 0) return mid;
                        }
                    }
                }
            }
            if (_event_1_gem.Count > 0)
            {
                if (_recent_merchants.Count > 0)
                {
                    if (_event_1_gem[0].id == _recent_merchants[_recent_merchants.Count - 1].id) // 事件1中第一位商人和最近商人匹配
                    {
                        // 查找是否有事件中下一个商人
                        int mid = 0;
                        foreach (TradeMerchant m in _refresh_merchants)
                        {
                            if (m.id == _event_1_gem[1].id) { mid = m.id; break; }
                        }
                        if (mid > 0) return mid;
                        else if (usecard)
                        {
                            card_used = true; return _event_1_gem[1].id;
                        }
                    }
                }
            }
            if (_event_2_silver.Count > 0)
            {
                if (_recent_merchants.Count > 0)
                {
                    if (_recent_merchants.Count == 1) // 最近商人只有一位
                    {
                        if (_event_2_silver[0].id == _recent_merchants[0].id) // 事件2中第一位商人和最近商人匹配
                        {
                            // 查找是否有事件中下一个商人
                            int mid = 0;
                            foreach (TradeMerchant m in _refresh_merchants)
                            {
                                if (m.id == _event_2_silver[1].id) { mid = m.id; break; }
                            }
                            if (mid > 0) return mid;
                        }
                    }
                    else if (_recent_merchants.Count >= 2) // 最近商人数>=2
                    {
                        // 如果事件2中前2位都匹配
                        if (_event_2_silver[0].id == _recent_merchants[_recent_merchants.Count - 2].id &&
                            _event_2_silver[1].id == _recent_merchants[_recent_merchants.Count - 1].id)
                        {
                            // 查找是否有事件中下一个商人
                            int mid = 0;
                            foreach (TradeMerchant m in _refresh_merchants)
                            {
                                if (m.id == _event_2_silver[2].id) { mid = m.id; break; }
                            }
                            if (mid > 0) return mid;
                            else if (usecard)
                            {
                                card_used = true; return _event_2_silver[2].id;
                            }
                        }
                        else if (_event_2_silver[0].id == _recent_merchants[_recent_merchants.Count - 1].id) // 事件2中第一位商人和最近商人匹配
                        {
                            // 查找是否有事件中下一个商人
                            int mid = 0;
                            foreach (TradeMerchant m in _refresh_merchants)
                            {
                                if (m.id == _event_2_silver[1].id) { mid = m.id; break; }
                            }
                            if (mid > 0) return mid;
                        }
                    }
                }
            }
            if (_event_1_silver.Count > 0)
            {
                if (_recent_merchants.Count > 0)
                {
                    if (_event_1_silver[0].id == _recent_merchants[_recent_merchants.Count - 1].id) // 事件1中第一位商人和最近商人匹配
                    {
                        // 查找是否有事件中下一个商人
                        int mid = 0;
                        foreach (TradeMerchant m in _refresh_merchants)
                        {
                            if (m.id == _event_1_silver[1].id) { mid = m.id; break; }
                        }
                        if (mid > 0) return mid;
                        else if (usecard)
                        {
                            card_used = true; return _event_1_silver[1].id;
                        }
                    }
                }
            }
            if (_event_2_stone.Count > 0)
            {
                if (_recent_merchants.Count > 0)
                {
                    if (_recent_merchants.Count == 1) // 最近商人只有一位
                    {
                        if (_event_2_stone[0].id == _recent_merchants[0].id) // 事件2中第一位商人和最近商人匹配
                        {
                            // 查找是否有事件中下一个商人
                            int mid = 0;
                            foreach (TradeMerchant m in _refresh_merchants)
                            {
                                if (m.id == _event_2_stone[1].id) { mid = m.id; break; }
                            }
                            if (mid > 0) return mid;
                        }
                    }
                    else if (_recent_merchants.Count >= 2) // 最近商人数>=2
                    {
                        // 如果事件2中前2位都匹配
                        if (_event_2_stone[0].id == _recent_merchants[_recent_merchants.Count - 2].id &&
                            _event_2_stone[1].id == _recent_merchants[_recent_merchants.Count - 1].id)
                        {
                            // 查找是否有事件中下一个商人
                            int mid = 0;
                            foreach (TradeMerchant m in _refresh_merchants)
                            {
                                if (m.id == _event_2_stone[2].id) { mid = m.id; break; }
                            }
                            if (mid > 0) return mid;
                            else if (usecard)
                            {
                                card_used = true; return _event_2_stone[2].id;
                            }
                        }
                        else if (_event_2_stone[0].id == _recent_merchants[_recent_merchants.Count - 1].id) // 事件2中第一位商人和最近商人匹配
                        {
                            // 查找是否有事件中下一个商人
                            int mid = 0;
                            foreach (TradeMerchant m in _refresh_merchants)
                            {
                                if (m.id == _event_2_stone[1].id) { mid = m.id; break; }
                            }
                            if (mid > 0) return mid;
                        }
                    }
                }
            }
            if (_event_1_stone.Count > 0)
            {
                if (_recent_merchants.Count > 0)
                {
                    if (_event_1_stone[0].id == _recent_merchants[_recent_merchants.Count - 1].id) // 事件1中第一位商人和最近商人匹配
                    {
                        // 查找是否有事件中下一个商人
                        int mid = 0;
                        foreach (TradeMerchant m in _refresh_merchants)
                        {
                            if (m.id == _event_1_stone[1].id) { mid = m.id; break; }
                        }
                        if (mid > 0) return mid;
                        else if (usecard)
                        {
                            card_used = true; return _event_1_stone[1].id;
                        }
                    }
                }
            }
            int nodiscover_mid = 0; // 查找未结识商人
            foreach (TradeMerchant m in _refresh_merchants)
            {
                if (!m.discovered) { nodiscover_mid = m.id; break; }
            }
            if (nodiscover_mid > 0) return nodiscover_mid;
            // 无未结识商人, 拿事件第一位商人
            int event_mid = 0;
            if (_event_2_gem.Count > 0)
            {
                foreach (TradeMerchant m in _refresh_merchants)
                {
                    if (m.id == _event_2_gem[0].id) { event_mid = m.id; break; }
                }
            }
            if (event_mid > 0) return event_mid;
            if (_event_1_gem.Count > 0)
            {
                foreach (TradeMerchant m in _refresh_merchants)
                {
                    if (m.id == _event_1_gem[0].id) { event_mid = m.id; break; }
                }
            }
            if (event_mid > 0) return event_mid;
            if (_event_2_silver.Count > 0)
            {
                foreach (TradeMerchant m in _refresh_merchants)
                {
                    if (m.id == _event_2_silver[0].id) { event_mid = m.id; break; }
                }
            }
            if (event_mid > 0) return event_mid;
            if (_event_1_silver.Count > 0)
            {
                foreach (TradeMerchant m in _refresh_merchants)
                {
                    if (m.id == _event_1_silver[0].id) { event_mid = m.id; break; }
                }
            }
            if (event_mid > 0) return event_mid;
            if (_event_2_stone.Count > 0)
            {
                foreach (TradeMerchant m in _refresh_merchants)
                {
                    if (m.id == _event_2_stone[0].id) { event_mid = m.id; break; }
                }
            }
            if (event_mid > 0) return event_mid;
            if (_event_1_stone.Count > 0)
            {
                foreach (TradeMerchant m in _refresh_merchants)
                {
                    if (m.id == _event_1_stone[0].id) { event_mid = m.id; break; }
                }
            }
            if (event_mid > 0) return event_mid;
            // 事件都没有一个, 选第一个
            return _refresh_merchants[0].id;
        }
        private List<string> getMerchants()
        {
            List<string> merchants = new List<string>();
            merchants.Add("楼兰商人"); merchants.Add("西域胡商"); merchants.Add("巴蜀商人");
            merchants.Add("大理商人"); merchants.Add("闽南商人"); merchants.Add("辽东商人");
            merchants.Add("关东商人"); merchants.Add("淮南商人"); merchants.Add("荆楚商人");
            merchants.Add("南越商人"); merchants.Add("浔阳商人"); merchants.Add("岭南商人");
            return merchants;
        }
        private class TradeMerchant
        {
            public int id;
            public string name;
            public bool discovered = false;
        }
        #endregion

        #region weave
        private void refreshWorker(ProtocolMgr protocol, ILogger logger, int workerId, int pos, int formerSkillId)
        {
            string url = "/root/make!refreshWeaverAttribute.action";
            string data = String.Format("pos={1}&playerMakerId={0}", workerId, pos);
            string desc = String.Format("刷新纺织工技能[{0}] ", WeaveWorker.getSkillName(formerSkillId));
            com.lover.astd.common.model.ServerResult result = protocol.postXml(url, data, desc);
            if (result == null || !result.CmdSucceed) return;
            XmlDocument xml = result.CmdResult;
            //<results>
            //  <state>1</state>
            //  <newskill>0</newskill>
            //  <sucadd>0</sucadd>
            //  <criadd>0</criadd>
            //  <leveladd>0</leveladd>
            //</results>
            XmlNode newskill_node = xml.SelectSingleNode("/results/newskill");
            if (newskill_node != null)
            {
                int newskill_id = 0;
                Int32.TryParse(newskill_node.InnerText, out newskill_id);
                if (newskill_id == 0) desc += ", 刷新失败, 技能不变";
                else
                {
                    desc += String.Format(", 刷新成功, 技能变为[{0}]", WeaveWorker.getSkillName(newskill_id));
                }
            }
            logInfo(logger, desc);
        }
        /// <summary>
        /// 0=success, 1=http failure, 2=work done, 3=not enough movable, 4=price not match, 10=other
        /// </summary>
        /// <param name="protocol"></param>
        /// <param name="logger"></param>
        /// <param name="user"></param>
        /// <param name="weave_price"></param>
        /// <param name="do_tired_weave"></param>
        /// <returns></returns>
        public int handleWeaveInfo(ProtocolMgr protocol, ILogger logger, User user, int weave_price, out int weave_state, bool do_tired_weave=false, bool only_free=true)
        {
            weave_state = 0;
            if (user.Level < 82) return 10;
            List<WeaveWorker> _workers = new List<WeaveWorker>();
            List<ClothInfo> _cloths = new List<ClothInfo>();
            int _price = 0;
            int _num_max = 0;
            int _self_techId = 0;
            bool _have_free_refreshWorker = false;
            int _weave_card_num = 0;
            int _weave_state = -1;
            int _weave_cost1 = 10;
            int _weave_cost2 = 30;
            int _weave_remainHigh = 0;
            int _weave_free_times = 0;

            string url = "/root/make.action";
            com.lover.astd.common.model.ServerResult result = protocol.getXml(url, "获取纺织信息");
            if (result == null) return 1;
            if(!result.CmdSucceed) return 10;

            XmlDocument xml = result.CmdResult;

            #region get info
            XmlNode cost1_node = xml.SelectSingleNode("/results/cost1");
            if (cost1_node != null) Int32.TryParse(cost1_node.InnerText, out _weave_cost1);
            XmlNode cost2_node = xml.SelectSingleNode("/results/cost2");
            if (cost2_node != null) Int32.TryParse(cost2_node.InnerText, out _weave_cost2);
            XmlNode status_node = xml.SelectSingleNode("/results/status");
            if (status_node != null) Int32.TryParse(status_node.InnerText, out _weave_state);
            XmlNode remainhigh_node = xml.SelectSingleNode("/results/remainhigh");
            if (remainhigh_node != null) Int32.TryParse(remainhigh_node.InnerText, out _weave_remainHigh);
            else _weave_remainHigh = 0;

            XmlNodeList card_nodes = xml.SelectNodes("/results/card");
            if (card_nodes != null)
            {
                foreach (XmlNode card_node in card_nodes)
                {
                    if (card_node == null || !card_node.HasChildNodes) continue;
                    XmlNode cardnum_node = card_node.SelectSingleNode("cardnum");
                    if (cardnum_node != null) Int32.TryParse(cardnum_node.InnerText, out _weave_card_num);
                }
            }

            XmlNode first_refresh_node = xml.SelectSingleNode("/results/firstrefresh");
            if (first_refresh_node != null) _have_free_refreshWorker = first_refresh_node.InnerText == "1";
            else _have_free_refreshWorker = false;

            XmlNode results = xml.SelectSingleNode("/results");
            XmlNodeList childs = results.ChildNodes;
            int price_isup = 0;
            bool is_master = false;
            foreach (XmlNode child in childs)
            {
                if (child.Name == "makenum") _weave_free_times = Int32.Parse(child.InnerText);
                else if (child.Name == "makemax") _num_max = Int32.Parse(child.InnerText);
                else if (child.Name == "price") _price = Int32.Parse(child.InnerText);
                else if (child.Name == "tech") _self_techId = Int32.Parse(child.InnerText);
                else if (child.Name == "up") price_isup = Int32.Parse(child.InnerText);
                else if (child.Name == "teacher") is_master = child.InnerText.Equals("1");
                else if (child.Name == "make")
                {
                    XmlNodeList make_infos = child.ChildNodes;
                    ClothInfo info = new ClothInfo();
                    foreach (XmlNode makeinfo in make_infos)
                    {
                        if (makeinfo.Name == "id") info.id = Int32.Parse(makeinfo.InnerText);
                        else if (makeinfo.Name == "type") info.type = Int32.Parse(makeinfo.InnerText);
                        else if (makeinfo.Name == "name") info.name = makeinfo.InnerText;
                        else if (makeinfo.Name == "cost") info.cost = Int32.Parse(makeinfo.InnerText);
                        else if (makeinfo.Name == "successp") info.success = float.Parse(makeinfo.InnerText);
                        else if (makeinfo.Name == "criticalp") info.critical = float.Parse(makeinfo.InnerText);
                        else if (makeinfo.Name == "sellprice") info.sellprice = Int32.Parse(makeinfo.InnerText);
                        else if (makeinfo.Name == "lv") info.level = Int32.Parse(makeinfo.InnerText);
                    }
                    _cloths.Add(info);
                }
                else if (child.Name == "playermaker")
                {
                    XmlNodeList worker_infos = child.ChildNodes;
                    WeaveWorker worker = new WeaveWorker();
                    foreach (XmlNode worker_node in worker_infos)
                    {
                        if (worker_node.Name == "id") worker.id = Int32.Parse(worker_node.InnerText);
                        else if (worker_node.Name == "skill") worker.skill = worker_node.InnerText;
                    }
                    _workers.Add(worker);
                }
            }
            if (!is_master) logInfo(logger, String.Format("当前布价: {0}{1}", _price, price_isup < 0 ? "↓" : "↑"));
            #endregion

            weave_state = _weave_state;
            // start do things
            if (_have_free_refreshWorker)
            {
                int skill_pos = 0, low_skill = 0;
                foreach (WeaveWorker worker in _workers)
                {
                    if (worker.haveLowSkill(out skill_pos, out low_skill))
                    {
                        refreshWorker(protocol, logger, worker.id, skill_pos, low_skill);
                        break;
                    }
                }
            }
            if(!is_master && _price < weave_price) return 4;
            if (_weave_state == 3) return 2;
            // 首先看有无免费次数, 有的话直接用掉
            if (_weave_free_times > 0) logInfo(logger, "发现免费纺织, 检查是否符合纺织条件");
            
            if (_weave_free_times == 0)
            {
                if (only_free) return 0;
                if (!do_tired_weave && _weave_state != 1) return 2;
                if (_weave_state == 1 && user.CurMovable < _weave_cost1) return 3;
                if (_weave_state == 2 && user.CurMovable < _weave_cost2) return 3;
            }

            List<WeaveAssist> sel_assists = null;
            if (!is_master)
            {
                List<WeaveAssist> all_assists = getWeaveAssistInfo(protocol, logger);
                sel_assists = getAssists(all_assists);
                List<ClothInfo> new_cloths = setAssist(protocol, logger, sel_assists);
                if (new_cloths != null && new_cloths.Count > 0) _cloths = new_cloths;
            }
            else
            {
                logInfo(logger, "纺织大师, 无需布价, 妙手来钱~~");
            }
            // sort clothinfos, order by sellprice desc
            for (int i = 0, j = 0, len = _cloths.Count; i < len - 2; i++)
            {
                for (j = i + 1; j < len - 1; j++)
                {
                    if (_cloths[i].sellprice < _cloths[j].sellprice)
                    {
                        ClothInfo tmp = _cloths[i];
                        _cloths[i] = _cloths[j];
                        _cloths[j] = tmp;
                    }
                }
            }
            // then find success > 90, weave
            ClothInfo cloth = null;
            for (int i = 0, len = _cloths.Count; i < len; i++)
            {
                if (_cloths[i].success >= 1.0)
                {
                    cloth = _cloths[i]; break;
                }
            }
            if (cloth == null) cloth = _cloths[0];
            if (cloth != null)
            {
                bool make_result = make(protocol, logger, cloth, sel_assists, _weave_card_num > 0);
                if (!make_result) return 10;
            }
            return 0;
        }
        private List<WeaveAssist> getWeaveAssistInfo(ProtocolMgr protocol, ILogger logger)
        {
            List<WeaveAssist> assists = new List<WeaveAssist>();
            string url = "/root/make!getWeaverAssInfo.action";
            com.lover.astd.common.model.ServerResult result = protocol.getXml(url, "获取纺织辅助人信息");
            if (result == null || !result.CmdSucceed) return assists;
            XmlDocument xml = result.CmdResult;

            XmlNode results = xml.SelectSingleNode("/results");
            XmlNodeList childs = results.ChildNodes;
            foreach (XmlNode child in childs)
            {
                if (child.Name == "assplayer")
                {
                    XmlNodeList nodes = child.ChildNodes;
                    WeaveAssist ass = new WeaveAssist();
                    foreach (XmlNode node in nodes)
                    {
                        if (node.Name == "playerid") ass.id = Int32.Parse(node.InnerText);
                        else if (node.Name == "playername") ass.name = node.InnerText;
                        else if (node.Name == "weaverlevel") ass.level = Int32.Parse(node.InnerText);
                    }
                    assists.Add(ass);
                }
            }
            return assists;
        }
        private List<ClothInfo> setAssist(ProtocolMgr protocol, ILogger logger, List<WeaveAssist> assists)
        {
            List<ClothInfo> _cloths = new List<ClothInfo>();
            string url = "/root/make.action";
            string data = String.Format("secondAssPId={0}&firstAssPId={1}", assists[0].id, assists[1].id);
            string desc = String.Format("设置纺织辅助人:[{0}({1}), {2}({3})] ",
                assists[0].name, assists[0].level, assists[1].name, assists[0].level);
            com.lover.astd.common.model.ServerResult result = protocol.postXml(url, data, "设置纺织辅助人");
            if (result == null || !result.CmdSucceed) return _cloths;
            XmlDocument xml = result.CmdResult;
            XmlNode results = xml.SelectSingleNode("/results");
            XmlNodeList childs = results.ChildNodes;
            foreach (XmlNode child in childs)
            {
                if (child.Name == "make")
                {
                    XmlNodeList make_infos = child.ChildNodes;
                    ClothInfo info = new ClothInfo();
                    foreach (XmlNode makeinfo in make_infos)
                    {
                        if (makeinfo.Name == "id") info.id = Int32.Parse(makeinfo.InnerText);
                        else if (makeinfo.Name == "type") info.type = Int32.Parse(makeinfo.InnerText);
                        else if (makeinfo.Name == "name") info.name = makeinfo.InnerText;
                        else if (makeinfo.Name == "cost") info.cost = Int32.Parse(makeinfo.InnerText);
                        else if (makeinfo.Name == "successp") info.success = float.Parse(makeinfo.InnerText);
                        else if (makeinfo.Name == "criticalp") info.critical = float.Parse(makeinfo.InnerText);
                        else if (makeinfo.Name == "sellprice") info.sellprice = Int32.Parse(makeinfo.InnerText);
                        else if (makeinfo.Name == "lv") info.level = Int32.Parse(makeinfo.InnerText);
                    }
                    _cloths.Add(info);
                }
            }
            logInfo(logger, desc);
            return _cloths;
        }
        private bool make(ProtocolMgr protocol, ILogger logger, ClothInfo cloth, List<WeaveAssist> assists, bool use_card)
        {
            string url = "/root/make!make.action";
            string data, desc;
            if (assists == null || assists.Count == 0)
            {
                data = String.Format("makeId={0}{1}", cloth.id, use_card ? "&mode=8" : "");
                desc = String.Format("纺织{0}, 织布[{1}]",
                    use_card ? "[使用纺织翻倍卡]" : "", cloth.name);
            }
            else
            {
                data = String.Format("makeId={0}&secondAssPId={1}&firstAssPId={2}{3}", cloth.id, assists[0].id, assists[1].id, use_card ? "&mode=8" : "");
                desc = String.Format("纺织{0}, 辅助人::[{1}({2}), {3}({4})], 织布[{5}]",
                    use_card ? "[使用纺织翻倍卡]" : "", assists[0].name, assists[0].level, assists[1].name, assists[0].level, cloth.name);
            }
            com.lover.astd.common.model.ServerResult result = protocol.postXml(url, data, "纺织");
            if (result == null || !result.CmdSucceed) return false;
            XmlDocument xml = result.CmdResult;
            XmlNode profit_node = xml.SelectSingleNode("/results/playerupdateinfo/makeresult/makeresult/profit");
            if (profit_node == null)
            {
                desc += ", 纺织失败";
                logInfo(logger, desc);
                return true;
            }
            int profit = Int32.Parse(profit_node.InnerText);
            desc += String.Format(", 银币+{0}", profit);
            logInfo(logger, desc);
            return true;
        }
        private string getTechName(int techId)
        {
            //<tech>11</tech>基础产量1
            //<tech>21</tech>海外暴击1
            //<tech>33</tech>大卖产量3
            //<tech>41</tech>成功1
            //<tech>52</tech>暴击2
            if (techId == 0) return "";
            string[] names = new string[] { "基础产量", "海外暴击", "大卖产量", "成功", "暴击" };
            int type = (int)(techId / 10);
            int factor = techId - type * 10;
            return names[type - 1] + factor;
        }
        private List<WeaveAssist> getAssists(List<WeaveAssist> assists)
        {
            List<WeaveAssist> ass = new List<WeaveAssist>();
            if (assists.Count == 0) { }
            else if (assists.Count == 1) ass.Add(assists[0]);
            else
            {
                ass.Add(assists[0]); ass.Add(assists[1]);
            }
            if (ass.Count < 2) ass.Add(new WeaveAssist());
            if (ass.Count < 2) ass.Add(new WeaveAssist()); // 有可能一个辅助都没有, 所以保险起见, 加2次空的
            return ass;
        }
        private class ClothInfo
        {
            //<id>49</id>
            //<type>2</type>
            //<name>杂色细棉布</name>
            //<cost>2681</cost>
            //<successp>0.5</successp>
            //<criticalp>0.3</criticalp>
            //<sellprice>18761</sellprice>
            //<lv>30</lv>
            //<intro>各种棉絮混杂纺织的棉布，质地较为精细。</intro>
            //<s>61</s>
            //<c>59</c>
            public int id;
            public int type;
            public string name;
            public int cost;
            public float success;
            public float critical;
            public int sellprice;
            public int level;
        }
        private class WeaveAssist
        {
            public int id;
            public string name;
            public int level;
        }
        private class WeaveWorker
        {
            //<playermaker>
            //    <id>6639</id>
            //    <playerid>36151</playerid>
            //    <lv>10</lv>
            //    <exp>1.0</exp>
            //    <turn>0</turn>
            //    <hasnext>1</hasnext>
            //    <skill>6,2,</skill>  ==> 1=级别+1, 2=暴击+3, 3=成功+3, 4=暴击+5, 5=成功+5, 6=暴击+8, 7=暴击+10, 8=成功+8, 9=成功+10
            //</playermaker>
            public int id;
            public string skill;
            public static string getSkillName(int skillId)
            {
                string[] skill_names = new string[] { "", "级别+1(满)", "暴击+3", "成功+3", "暴击+5", "成功+5", "暴击+8", "暴击+10(满)", "成功+8", "成功+10(满)" };
                if (skillId > skill_names.Length - 1) return "";
                return skill_names[skillId];
            }
            public bool haveLowSkill(out int lowSkillPos, out int lowSkillId)
            {
                lowSkillPos = 0;
                lowSkillId = 0;
                if (skill == null || skill.Equals("null")) return false;
                string[] skills = skill.Split(',');
                if (skills.Length < 2) return false;
                int skill_1 = 0, skill_2 = 0;
                Int32.TryParse(skills[0], out skill_1);
                Int32.TryParse(skills[1], out skill_2);
                if (skill_1 > 0 && skill_1 != 1 && skill_1 != 7 && skill_1 != 9)
                {
                    lowSkillPos = 1;
                    lowSkillId = skill_1;
                    return true;
                }
                if (skill_2 > 0 && skill_2 != 1 && skill_2 != 7 && skill_2 != 9)
                {
                    lowSkillPos = 2;
                    lowSkillId = skill_2;
                    return true;
                }
                return false;
            }
        }
        #endregion

        #region refine
        /// <summary>
        /// 0=success, 1=http failure, 2=work done, 3=not enough movable,4=cd 10=other
        /// </summary>
        /// <param name="protocol"></param>
        /// <param name="logger"></param>
        /// <param name="user"></param>
        /// <param name="goldPerGem"></param>
        /// <param name="do_tired_refine"></param>
        /// <returns></returns>
        public int handleRefineInfo(ProtocolMgr protocol, ILogger logger, User user, double goldPerGem, 
            int gold_available, int reserve_count, bool do_tired_refine=false)
        {
            int _refine_cost1 = 0, _refine_cost2 = 0, _refine_state = 0, _refine_remainHigh = 0;
            int _perMinerRefreshGold = 0;
            int _refine_number = 0;
            List<int> _refine_groupids = new List<int>();
            List<Refiner> _miners = new List<Refiner>();

            string url = "/root/refine!getRefineInfo.action";
            com.lover.astd.common.model.ServerResult result = protocol.getXml(url, "获取精炼信息");
            if (result == null) return 1;
            if(!result.CmdSucceed) return 10;
            XmlDocument xml = result.CmdResult;

            XmlNode cost1_node = xml.SelectSingleNode("/results/cost1");
            if (cost1_node != null) Int32.TryParse(cost1_node.InnerText, out _refine_cost1);
            XmlNode cost2_node = xml.SelectSingleNode("/results/cost2");
            if (cost2_node != null) Int32.TryParse(cost2_node.InnerText, out _refine_cost2);
            XmlNode status_node = xml.SelectSingleNode("/results/status");
            if (status_node != null) Int32.TryParse(status_node.InnerText, out _refine_state);

            if (!do_tired_refine && _refine_state != 1) return 2;
            if (_refine_state == 1 && user.CurMovable < _refine_cost1) return 3;
            if (_refine_state == 2 && user.CurMovable < _refine_cost2) return 3;

            int refine_level = 1;
            XmlNode refinelevel_node = xml.SelectSingleNode("/results/refinelv");
            if (refinelevel_node != null) Int32.TryParse(refinelevel_node.InnerText, out refine_level);

            XmlNode remainhigh_node = xml.SelectSingleNode("/results/remainhigh");
            if (remainhigh_node != null) Int32.TryParse(remainhigh_node.InnerText, out _refine_remainHigh);

            XmlNode percost_node = xml.SelectSingleNode("/results/percost");
            if (percost_node != null) Int32.TryParse(percost_node.InnerText, out _perMinerRefreshGold);
            
            XmlNode results = xml.SelectSingleNode("/results");
            XmlNodeList childs = results.ChildNodes;
            foreach (XmlNode child in childs)
            {
                if (child.Name == "refinergroup")
                {
                    XmlNodeList group_childs = child.ChildNodes;
                    int groupid = 0, cdflag = 0; long time = 0;
                    foreach (XmlNode gnode in group_childs)
                    {
                        if (gnode.Name == "id") groupid = Int32.Parse(gnode.InnerText);
                        else if (gnode.Name == "cdflag") cdflag = Int32.Parse(gnode.InnerText);
                        else if (gnode.Name == "time") time = Int64.Parse(gnode.InnerText);
                    }
                    if (time == 0) _refine_groupids.Add(groupid);
                }
                else if (child.Name == "refiner")
                {
                    XmlNodeList refiner_childs = child.ChildNodes;
                    Refiner refiner = new Refiner();
                    foreach (XmlNode rnode in refiner_childs)
                    {
                        if (rnode.Name == "id") refiner.Id = Int32.Parse(rnode.InnerText);
                        else if (rnode.Name == "name") refiner.Name = rnode.InnerText;
                        else if (rnode.Name == "color") refiner.Color = rnode.InnerText;
                    }
                    _miners.Add(refiner);
                }
                else if (child.Name == "refinenum") _refine_number = Int32.Parse(child.InnerText);
            }
            if (_refine_groupids.Count == 0) return 4;
            if (_refine_number < refine_level || _refine_number < reserve_count) return 2;
            int refreshIndex = -1;
            int refine_result = 0;
            if (ifNeedRefreshMiner(_miners, _perMinerRefreshGold, goldPerGem, out refreshIndex))
            {
                // 查看是否会超过金币限制
                if (gold_available >= _perMinerRefreshGold)
                {
                    if (refreshMiner(protocol, logger, _perMinerRefreshGold, refreshIndex)) refine_result = refine(protocol, logger);
                }
                else refine_result = refine(protocol, logger);
            }
            else refine_result = refine(protocol, logger);
            return refine_result;
        }
        private bool ifNeedRefreshMiner(List<Refiner> _miners, int upgrade_gold, double goldPerGem, out int index)
        {
            index = -1;
            if (_miners.Count < 3) return false;
            // 白色=0, 蓝色=1, 绿色=2, 黄色=3, 红色=4, 紫色=5
            int color1 = _miners[0].getColorInt(), color2 = _miners[1].getColorInt(), color3 = _miners[2].getColorInt();

            // 如果当前已经有事件, 那么不需要升级
            int eventAwardGemCount = 0;
            int evt = getRefineEvent(color1, color2, color3, out eventAwardGemCount);
            if (evt > 0) return false;

            int eventAwardGemCount1 = 0, eventAwardGemCount2 = 0, eventAwardGemCount3 = 0;
            int evt1 = 0, evt2 = 0, evt3 = 0;
            if (color1 >= 5) evt1 = 0;
            else evt1 = getRefineEvent(color1 + 1, color2, color3, out eventAwardGemCount1);
            if (color2 >= 5) evt2 = 0;
            else evt2 = getRefineEvent(color1, color2 + 1, color3, out eventAwardGemCount2);
            if (color3 >= 5) evt3 = 0;
            else evt3 = getRefineEvent(color1, color2, color3 + 1, out eventAwardGemCount3);

            if (evt1 > 0 || evt2 > 0 || evt3 > 0)
            {
                // 找到最大的宝石数
                if (eventAwardGemCount1 > eventAwardGemCount2 && eventAwardGemCount1 > eventAwardGemCount3)
                {
                    index = 1;
                    if (upgrade_gold == 0) return true;
                    else
                    {
                        double ratio = upgrade_gold * 1.0 / eventAwardGemCount1;
                        if (ratio <= goldPerGem) return true;
                    }
                }
                else if (eventAwardGemCount2 > eventAwardGemCount1 && eventAwardGemCount2 > eventAwardGemCount3)
                {
                    index = 2;
                    if (upgrade_gold == 0) return true;
                    else
                    {
                        double ratio = upgrade_gold * 1.0 / eventAwardGemCount2;
                        if (ratio <= goldPerGem) return true;
                    }
                }
                else if (eventAwardGemCount3 > eventAwardGemCount1 && eventAwardGemCount3 > eventAwardGemCount2)
                {
                    index = 3;
                    if (upgrade_gold == 0) return true;
                    else
                    {
                        double ratio = upgrade_gold * 1.0 / eventAwardGemCount3;
                        if (ratio <= goldPerGem) return true;
                    }
                }
            }
            return false;
        }
        /// <summary>
        /// 返回是否有事件发生
        /// 返回值为: 0=无, 1=三个臭皮匠, 2=步步攀升, 3=好事成双, 4=一枝独秀
        /// </summary>
        /// <param name="color1"></param>
        /// <param name="color2"></param>
        /// <param name="color3"></param>
        /// <returns>0=无, 1=三个臭皮匠, 2=步步攀升, 3=好事成双, 4=一枝独秀</returns>
        private int getRefineEvent(int color1, int color2, int color3, out int eventAwardGemCount)
        {
            eventAwardGemCount = 0;
            // 白色=0, 蓝色=1, 绿色=2, 黄色=3, 红色=4, 紫色=5
            // 首先看是否有三个相同
            if (color1 == color2 && color1 == color3 && color2 == color3)
            {
                int[] awards = new int[] { 2, 3, 4, 6, 10, 16 };
                eventAwardGemCount = awards[color1];
                return 1;
            }

            // 再看是否有步步攀升
            int[] colors = new int[] { color1, color2, color3 };
            for (int i = 0; i < 2; i++)
            {
                for (int j = i + 1; j < 3; j++)
                {
                    if (colors[i] > colors[j])
                    {
                        int tmp = colors[i];
                        colors[i] = colors[j];
                        colors[j] = tmp;
                    }
                }
            }
            if (colors[0] + 1 == colors[1] && colors[1] + 1 == colors[2])
            {
                int[] awards = new int[] { 3, 4, 6, 10 };
                eventAwardGemCount = awards[colors[0]];
                return 2;
            }

            // 再看是否有一枝独秀
            // 必须有2个蓝的或者白色, 然后另外一个是紫或者红
            if (colors[2] >= 4 && colors[1] == colors[0] && colors[1] <= 1)
            {
                int[] awards = new int[] { 6, 8 };
                eventAwardGemCount = awards[colors[2] - 4];
                return 3;
            }
            // 再看是否有好事成双
            if ((colors[2] == colors[1] && colors[2] >= 3) || (colors[1] == colors[0] && colors[1] >= 3))
            {
                int[] awards = new int[] { 4, 6, 10 };
                eventAwardGemCount = awards[colors[1] - 3];
                return 4;
            }
            return 0;
        }
        /// <summary>
        /// return 0=success, 1=http error, 10=cmd error
        /// </summary>
        /// <returns></returns>
        public int refine(ProtocolMgr protocol, ILogger logger)
        {
            string url = "/root/refine!refine.action";
            string desc = "精炼";
            com.lover.astd.common.model.ServerResult result = protocol.getXml(url, desc);
            if (result == null) return 1;
            if (!result.CmdSucceed) return 10;
            XmlDocument xml = result.CmdResult;
            XmlNode results = xml.SelectSingleNode("/results");
            XmlNodeList childs = results.ChildNodes;
            int stone = 0, orig_stone = 0, gem = 0, critical = 0; string eventinfo = "";
            foreach (XmlNode child in childs)
            {
                if (child.Name == "bowlder") stone = Int32.Parse(child.InnerText);
                else if (child.Name == "stone") orig_stone = Int32.Parse(child.InnerText);
                else if (child.Name == "baoshi") gem = Int32.Parse(child.InnerText);
                else if (child.Name == "baoji") critical = Int32.Parse(child.InnerText);
                else if (child.Name == "eventintro") eventinfo = child.InnerText;
            }

            if (critical != 0) desc += "<<暴击>>, ";
            else desc += ", ";
            if (eventinfo != "") desc += String.Format("获得精炼事件:{0}, ", eventinfo);
            desc += String.Format("获得玉石+{0}, 原石+{1}", stone, orig_stone);
            if (gem > 0) desc += String.Format(", 宝石+{0}", gem);
            logInfo(logger, desc);
            return 0;
        }
        public bool refreshMiner(ProtocolMgr protocol, ILogger logger, int upgrade_gold, int orderId)
        {
            string url = "/root/refine!refreshOneRefiner.action";
            string data = "refinerOrder=" + orderId;
            string desc = String.Format("升级精炼工人{0}, 消耗金币{1}", orderId, upgrade_gold);
            com.lover.astd.common.model.ServerResult result = protocol.postXml(url, data, desc);
            if (result == null || !result.CmdSucceed) return false;
            XmlDocument xml = result.CmdResult;
            XmlNode results = xml.SelectSingleNode("/results");
            //<results><state>1</state><message></message></results>
            logInfo(logger, desc);
            return true;
        }
        private class Refiner : AsObject
        {
            private string _color;
            public string Color
            {
                get { return _color; }
                set { _color = value; }
            }
            /// <summary>
            /// 白色=0, 蓝色=1, 绿色=2, 黄色=3, 红色=4, 紫色=5
            /// </summary>
            /// <returns></returns>
            public int getColorInt()
            {
                int index = 0;
                string[] array = new string[] { "白", "蓝", "绿", "黄", "红", "紫" };
                for (int i = 0; i < array.Length; i++)
                {
                    if (array[i].Equals(_color))
                    {
                        index = i;
                        break;
                    }
                }
                return index;
            }
        }
        #endregion

        #region refine factory
        /// <summary>
        /// 0=success, 1=http failure, 2=work done, 3=not enough movable, 4=not enough silver, 10=other
        /// </summary>
        /// <param name="protocol"></param>
        /// <param name="logger"></param>
        /// <param name="_refine_weapon_name"></param>
        /// <param name="silver_available"></param>
        /// <param name="do_tired_refine"></param>
        public int handleRefineFactoryInfo(ProtocolMgr protocol, ILogger logger, User user, string _refine_weapon_name, int silver_available, bool do_tired_refine=false)
        {
            int _redWeaponCost = 0, _purepleWeaponCost = 0, _refineFactory_level = 0;
            int _refineFactory_cost1 = 0, _refineFactory_cost2 = 0, _refineFactory_state = 0;
            int _refineFactory_remainHigh = 0;
            int _refine_weapon_id = 0;

            string url = "/root/refine!getRefineFactory.action";
            com.lover.astd.common.model.ServerResult result = protocol.getXml(url, "获取炼制信息");
            if (result == null) return 1;
            if(!result.CmdSucceed) return 10;
            XmlDocument xml = result.CmdResult;

            XmlNode redWeponeCost_node = xml.SelectSingleNode("/results/red");
            if (redWeponeCost_node != null) Int32.TryParse(redWeponeCost_node.InnerText, out _redWeaponCost);
            XmlNode purpleWeponeCost_node = xml.SelectSingleNode("/results/zi");
            if (purpleWeponeCost_node != null) Int32.TryParse(purpleWeponeCost_node.InnerText, out _purepleWeaponCost);
            XmlNode lv_node = xml.SelectSingleNode("/results/lv");
            if (lv_node != null) Int32.TryParse(lv_node.InnerText, out _refineFactory_level);

            XmlNode cost1_node = xml.SelectSingleNode("/results/cost1");
            if (cost1_node != null) Int32.TryParse(cost1_node.InnerText, out _refineFactory_cost1);
            XmlNode cost2_node = xml.SelectSingleNode("/results/cost2");
            if (cost2_node != null) Int32.TryParse(cost2_node.InnerText, out _refineFactory_cost2);
            XmlNode status_node = xml.SelectSingleNode("/results/status");
            if (status_node != null) Int32.TryParse(status_node.InnerText, out _refineFactory_state);
            XmlNode remainhigh_node = xml.SelectSingleNode("/results/remainhigh");
            if (remainhigh_node != null) Int32.TryParse(remainhigh_node.InnerText, out _refineFactory_remainHigh);

            if (!do_tired_refine && _refineFactory_state != 1) return 2;
            if (_refineFactory_state == 1 && user.CurMovable < _refineFactory_cost1) return 3;
            if (_refineFactory_state == 2 && user.CurMovable < _refineFactory_cost2) return 3;

            int quality = 5;
            XmlNodeList weapons = xml.SelectNodes("/results/troop");
            foreach (XmlNode weapon_node in weapons)
            {
                string weaponid = "", weaponname = "";
                XmlNodeList subs = weapon_node.ChildNodes;
                foreach (XmlNode sub in subs)
                {
                    if (sub.Name == "name") weaponname = sub.InnerText;
                    else if (sub.Name == "troopid") weaponid = sub.InnerText;
                    else if (sub.Name == "quality") quality = Int32.Parse(sub.InnerText);
                }
                if (weaponname.IndexOf(_refine_weapon_name) >= 0)
                {
                    Int32.TryParse(weaponid, out _refine_weapon_id);
                    break;
                }
            }
            if (quality == 5 && silver_available < _redWeaponCost) return 4;
            if (quality == 6 && silver_available < _purepleWeaponCost) return 4;

            bool refine_ok = refineItem(protocol, logger, _refine_weapon_id, _refine_weapon_name, _refineFactory_level);
            if (refine_ok) return 0;
            return 10;
        }
        public bool refineItem(ProtocolMgr protocol, ILogger logger, int _refine_id, string _refine_name, int refine_level)
        {
            if (_refine_id == 0) return false;
            string url = "/root/refine!doRefineFactory.action";
            string data = "troopId=" + _refine_id;

            com.lover.astd.common.model.ServerResult result = protocol.postXml(url, data, "炼制物品");
            if (result == null || !result.CmdSucceed) return false;
            XmlDocument xml = result.CmdResult;
            //<results><state>1</state><message></message></results>
            string desc = String.Format("炼制物品[{0}*{1}]成功", _refine_name, refine_level);
            logInfo(logger, desc);
            return true;
        }
        #endregion

        #region nation task
        public void handleNationTaskInfo(ProtocolMgr protocol, ILogger logger, User user)
        {
            // first get nation task reward
            if (user._can_get_nation_task_reward)
            {
                if (getNationTaskReward(protocol, logger)) user._can_get_nation_task_reward = false;
            }

            string url = "/root/nation!getNationTask.action";
            ServerResult result = protocol.getXml(url, "获取国家任务信息");
            if (result == null || !result.CmdSucceed) return;
            XmlDocument xml = result.CmdResult;
            XmlNode results = xml.SelectSingleNode("/results");
            XmlNode running_task = results.SelectSingleNode("/results/nationtask");
            if (running_task != null) return;

            int support_gold = 0;
            XmlNode agree_gold_node = results.SelectSingleNode("agreegold");
            if(agree_gold_node != null) Int32.TryParse(agree_gold_node.InnerText, out support_gold);

            int support_id = 0;
            string support_player = "", support_name = "";
            XmlNodeList jinyan_nodes = results.SelectSingleNode("jinyan").ChildNodes;
            foreach (XmlNode jnode in jinyan_nodes)
            {
                if (jnode.Name != "nationtask") continue;
                XmlNodeList childs = jnode.ChildNodes;
                bool agreed = false;
                foreach (XmlNode child in childs)
                {
                    if (child.Name == "agreestatus") agreed = child.InnerText != "0";
                    else if (child.Name == "id") support_id = Int32.Parse(child.InnerText);
                    else if (child.Name == "name") support_name = child.InnerText;
                    else if (child.Name == "playername") support_player = child.InnerText;
                }
                if (!agreed) break;
                support_id = 0; // 此处为已经支持过的任务, 重置为0
            }
            if (support_gold == 0 && support_id > 0) supportTask(protocol, logger, support_id, support_player, support_name);
        }
        public bool getNationTaskReward(ProtocolMgr protocol, ILogger logger)
        {
            string url = "/root/nation!getNationTaskReward.action";
            ServerResult result = protocol.getXml(url, "获取国家任务信息奖励");
            if (result == null || !result.CmdSucceed) return false;
            XmlNode results = result.CmdResult.SelectSingleNode("/results");
            return true;
        }
        private bool supportTask(ProtocolMgr protocol, ILogger logger, int support_id, string support_player, string support_name)
        {
            string url = "/root/nation!agreeNationTask.action";
            string data = "jinyanId=" + support_id;
            string desc = String.Format("支持 [{0}] 进言 [{1}]", support_player, support_name);
            ServerResult result = protocol.postXml(url, data, desc);
            if (result == null || !result.CmdSucceed) return false;
            logInfo(logger, desc);
            return true;
        }
        #endregion

        #region daily task
        /// <summary>
        /// 0=success, 1=http failure, 2=work done today
        /// </summary>
        /// <param name="protocol"></param>
        /// <param name="logger"></param>
        /// <returns></returns>
        public int handleDailyTaskInfo(ProtocolMgr protocol, ILogger logger)
        {
            string url = "/root/task!getPerdayTask.action";
            com.lover.astd.common.model.ServerResult result = protocol.getXml(url, "获取每日任务信息");
            if (result == null) return 1;
            if(!result.CmdSucceed) return 10;
            XmlDocument xml = result.CmdResult;

            int handle_result = handleTaskInfo(protocol, logger, xml);
            if (handle_result == 1) return 2;
            return 0;
        }
        /// <summary>
        /// 0=success, 1=work done today
        /// </summary>
        /// <param name="protocol"></param>
        /// <param name="logger"></param>
        /// <param name="xml"></param>
        /// <returns></returns>
        private int handleTaskInfo(ProtocolMgr protocol, ILogger logger, XmlDocument xml)
        {
            int[] _rewardIds_can_get = new int[6];
            int _remain_tasknum = 0;
            bool _doing_task = false;
            long _task_time_remain = 0; // 该任务还有多长时间完成
            List<int> _combos_need = new List<int>();
            int _combo_score = 0;
            List<TaskItem> _nowTasks = new List<TaskItem>();

            for (int i = 0; i < _rewardIds_can_get.Length; i++) _rewardIds_can_get[i] = 0;
            XmlNode scorelist_node = xml.SelectSingleNode("/results/scorelist");
            if (scorelist_node != null)
            {
                int nowscore = 0;
                XmlNode nowscore_node = xml.SelectSingleNode("/results/score");
                if (nowscore_node != null) Int32.TryParse(nowscore_node.InnerText, out nowscore);
                string[] scoreliststrs = scorelist_node.InnerText.Split(',');
                List<int> scores = new List<int>();
                foreach (string str in scoreliststrs)
                {
                    if (str == null || str.Length == 0) continue;
                    int sc = 1000000;
                    Int32.TryParse(str, out sc);
                    scores.Add(sc);
                }
                for (int i = 0; i < scores.Count; i++)
                {
                    if (nowscore >= scores[i]) _rewardIds_can_get[i] = 1;
                }
                XmlNode already_get_node = xml.SelectSingleNode("/results/scorerewardlist");
                if (already_get_node != null)
                {
                    string[] got_strs = already_get_node.InnerText.Split(':');
                    scores.Clear();
                    foreach (string str in got_strs)
                    {
                        if (str == null || str.Length == 0) continue;
                        int got = 0;
                        Int32.TryParse(str, out got);
                        if (got > 0) scores.Add(got);
                    }
                    for (int i = 0; i < scores.Count && i < _rewardIds_can_get.Length; i++)
                    {
                        _rewardIds_can_get[i] = 0; // 已经拿取过奖励
                    }
                }
            }

            XmlNode isdoing = xml.SelectSingleNode("/results/status");
            if (isdoing != null) _doing_task = isdoing.InnerText == "1";

            XmlNode time_node = xml.SelectSingleNode("/results/secretarytime");
            if (time_node != null) _task_time_remain = Int64.Parse(time_node.InnerText);

            XmlNode results = xml.SelectSingleNode("/results");
            XmlNodeList childs = results.ChildNodes;
            foreach (XmlNode child in childs)
            {
                if (child.Name == "remainnum")
                {
                    _remain_tasknum = Int32.Parse(child.InnerText);
                }
                else if (child.Name == "combo")
                {
                    string[] combos = child.InnerText.Split(',');
                    foreach (string combo in combos)
                    {
                        if (combo == null || combo == "") continue;
                        string[] inners = combo.Split(':');
                        if (inners[1] == "0") _combos_need.Add(Int32.Parse(inners[0]));
                    }
                }
                else if (child.Name == "comboreward")
                {
                    Int32.TryParse(child.InnerText, out _combo_score);
                }
                else if (child.Name == "task")
                {
                    XmlNodeList task_nodes = child.ChildNodes;
                    TaskItem item = new TaskItem();
                    foreach (XmlNode tnode in task_nodes)
                    {
                        if (tnode.Name == "id") item.id = Int32.Parse(tnode.InnerText);
                        else if (tnode.Name == "type") item.type = Int32.Parse(tnode.InnerText);
                        else if (tnode.Name == "quality") item.quality = Int32.Parse(tnode.InnerText);
                        else if (tnode.Name == "name") item.name = tnode.InnerText;
                        else if (tnode.Name == "reward") item.reward = Int32.Parse(tnode.InnerText);
                    }
                    _nowTasks.Add(item);
                }
            }
            if (_combo_score >= 50) tryUseCard(protocol, logger, xml);
            else tryCancelCard(protocol, logger, xml);

            for (int i = 0; i < _rewardIds_can_get.Length; i++)
            {
                // 看看哪一项可以领
                if (_rewardIds_can_get[i] > 0) getTaskAward(protocol, logger, i + 1);
            }
            if (_remain_tasknum == 0) return 1;
            if (_doing_task) cancelTask(protocol, logger); // 本服务是每21分钟执行一次, 因此, 如果有在进行的任务, 肯定要取消
            else
            {
                TaskItem combo_item = null, highscore_item = null;
                foreach (TaskItem item in _nowTasks)
                {
                    // 如果发现了50分以上的任务, 直接选取, 否则选取combo的, 如果没有combo的, 直接选最高分的
                    if (_combos_need.IndexOf(item.type) >= 0)
                    {
                        if (combo_item == null || combo_item.reward < item.reward) combo_item = item;
                    }
                    if (highscore_item == null || highscore_item.reward < item.reward) highscore_item = item;
                }
                if (highscore_item != null)
                {
                    if (combo_item != null) selectTask(protocol, logger, combo_item.id);
                    else selectTask(protocol, logger, highscore_item.id);
                    autoTask(protocol, logger);
                }
                else if (combo_item != null)
                {
                    selectTask(protocol, logger, combo_item.id);
                    autoTask(protocol, logger);
                }
            }
            return 0;
        }
        private void selectTask(ProtocolMgr protocol, ILogger logger, int taskId)
        {
            string url = "/root/task!choosePerdayTask.action";
            string data = "taskId=" + taskId;
            com.lover.astd.common.model.ServerResult result = protocol.postXml(url, data, "选择每日任务");
            if (result == null || !result.CmdSucceed) return;
            XmlDocument xml = result.CmdResult;
            logInfo(logger, "选择新任务");
        }
        private void autoTask(ProtocolMgr protocol, ILogger logger)
        {
            string url = "/root/secretary!addTask.action";
            com.lover.astd.common.model.ServerResult result = protocol.postXml(url, "tid=13", "自动每日任务");
            if (result == null || !result.CmdSucceed) return;
            XmlDocument xml = result.CmdResult;
            //<results><state>1</state><message></message></results>
        }

        private void cancelTask(ProtocolMgr protocol, ILogger logger)
        {
            string url = "/root/task!cancelPerdayTask.action";
            com.lover.astd.common.model.ServerResult result = protocol.getXml(url, "取消每日任务");
            if (result == null || !result.CmdSucceed) return;
            XmlDocument xml = result.CmdResult;

            handleTaskInfo(protocol, logger, xml);
            logInfo(logger, "取消原有任务");
        }
        public void getTaskAward(ProtocolMgr protocol, ILogger logger, int rewardId)
        {
            string url = "/root/task!getPerdayTaskReward.action";
            string data = "rewardId=" + rewardId;
            com.lover.astd.common.model.ServerResult result = protocol.postXml(url, data, "拿取每日任务奖励");
            if (result == null || !result.CmdSucceed) return;
            XmlDocument xml = result.CmdResult;
            //<results>
            //  <state>1</state>
            //  <reward>
            //    <scorelist>300,450,550,700,800,900,</scorelist>
            //    <scorelistpic>copper,token,copper,baoshi,baoshi,baoshi,</scorelistpic>
            //    <item>
            //      <name>军令</name>
            //      <num>5</num>
            //      <baoshilevel>0</baoshilevel>
            //      <chip>0</chip>
            //    </item>
            //  </reward>
            //  <scorerewardlist>1:1:</scorerewardlist>
            //</results>
            string name = "", num = "";
            XmlNode name_node = xml.SelectSingleNode("/results/reward/item/name");
            if (name_node != null) name = name_node.InnerText;
            XmlNode num_node = xml.SelectSingleNode("/results/reward/item/num");
            if (num_node != null) num = num_node.InnerText;
            logInfo(logger, String.Format("拿取每日任务奖励, {0}+{1}", name, num));
        }
        private class TaskItem
        {
            public int id = 0;
            public int type = 0;
            public int quality = 0;
            public string name = "";
            public int reward = 0;
        }
        #endregion

        #region seceratry
        /// <summary>
        /// 0=success, 1=http failure, 2=work done today, 10=other
        /// </summary>
        /// <param name="protocol"></param>
        /// <param name="logger"></param>
        /// <returns></returns>
        public int handleSecretaryInfo(ProtocolMgr protocol, ILogger logger, out long next_cd)
        {
            next_cd = 0;
            int token_remains = 0, get_token_cd = 0;
            int _foodHarvestRemains = 0, _stoneHarvestRemains = 0;

            string url = "/root/secretary.action";
            ServerResult result = protocol.getXml(url, "获取玩家小秘书信息");
            if (result == null) return 1;
            if(!result.CmdSucceed) return 10;
            XmlDocument xml = result.CmdResult;
            XmlNode totalTokenNode = xml.SelectSingleNode("/results/maxtokennum");
            XmlNode gotTokenNode = xml.SelectSingleNode("/results/tokennum");
            XmlNode tokenCdNode = xml.SelectSingleNode("/results/cd");
            if (totalTokenNode != null && gotTokenNode != null && tokenCdNode != null)
            {
                int totalToken = Int32.Parse(totalTokenNode.InnerText);
                int gotToken = Int32.Parse(gotTokenNode.InnerText);
                token_remains = totalToken - gotToken;
                get_token_cd = Int32.Parse(tokenCdNode.InnerText);
            }
            XmlNode foodRemainNode = xml.SelectSingleNode("/results/lin");
            if (foodRemainNode != null) _foodHarvestRemains = Int32.Parse(foodRemainNode.InnerText);
            XmlNode stoneRemainNode = xml.SelectSingleNode("/results/remainharvesttime");
            if (stoneRemainNode != null) _stoneHarvestRemains = Int32.Parse(stoneRemainNode.InnerText);

            if (token_remains == 0 && _foodHarvestRemains == 0 && _stoneHarvestRemains == 0) return 2;

            bool token_over = false, food_over = false, stone_over = false;
            if (token_remains > 0 && get_token_cd == 0)
            {
                if (!getFreeToken(protocol, logger, out token_remains, out get_token_cd)) token_over = false;
                else token_over = token_remains == 1;
            }
            
            if (_foodHarvestRemains > 0)
            {
                for (int i = 0; i < _foodHarvestRemains; i++)
                {
                    if (!harvestFood(protocol, logger)) food_over = false;
                    else food_over = (--_foodHarvestRemains == 0);
                }
            }
            if (_stoneHarvestRemains > 0)
            {
                for (int i = 0; i < _stoneHarvestRemains; i++)
                {
                    if (!harvestStone(protocol, logger)) stone_over = false;
                    else stone_over = (--_stoneHarvestRemains == 0);
                }
            }
            next_cd = get_token_cd;
            if (token_over && food_over && stone_over) return 2;
            return 0;
        }
        private class GiftInfo
        {
            //<gift>
            //    <id>12926</id>
            //    <content>tickets:12000,baoshi:100</content>
            //    <endtime>2013-10-25 00:00:00</endtime>
            //    <intime>1</intime>
            //    <name>1022祭祀送点券</name>
            //    <statuts>0</statuts>
            //</gift>
            public string id;
            public string intime;
            public string content;
            public string name;
            public string status;
            public string getContentDesc()
            {
                string result = "";
                string[] items = content.Split(',');
                foreach (string item in items)
                {
                    if (item == null || item.Length == 0) continue;
                    string[] values = item.Split(':');
                    if (values.Length < 2)
                    {
                        result += item;
                        continue;
                    }
                    string type = values[0], num = values[1];
                    string typedesc = type;
                    if (type.IndexOf("gold") >= 0) typedesc = "金币";
                    else if (type.IndexOf("silver") >= 0) typedesc = "银币";
                    else if (type.IndexOf("ticket") >= 0) typedesc = "点券";
                    else if (type.IndexOf("baoshi") >= 0) typedesc = "宝石";
                    result += String.Format("{0}+{1} ", typedesc, num);
                }

                return result;
            }
        }
        public void handleGiftInfo(ProtocolMgr protocol, ILogger logger)
        {
            string url = "/root/newGift!getNewGiftList.action";
            ServerResult result = protocol.getXml(url, "获取玩家礼包信息");
            if (result == null || !result.CmdSucceed) return;
            XmlDocument xml = result.CmdResult;

            XmlNodeList gift_nodes = xml.SelectNodes("/results/gift");
            List<GiftInfo> gifts = new List<GiftInfo>();
            foreach (XmlNode gift_node in gift_nodes)
            {
                if (gift_node == null || !gift_node.HasChildNodes) continue;
                XmlNodeList childs = gift_node.ChildNodes;
                GiftInfo gft = new GiftInfo();
                foreach (XmlNode child in childs)
                {
                    if (child.Name == "id") gft.id = child.InnerText;
                    else if (child.Name == "name") gft.name = child.InnerText;
                    else if (child.Name == "content") gft.content = child.InnerText;
                    else if (child.Name == "intime") gft.intime = child.InnerText;
                    else if (child.Name == "statuts") gft.status = child.InnerText;
                }
                if (gft.intime == "1" && gft.status == "0") getGiftReward(protocol, logger, gft);
            }
        }
        private void getGiftReward(ProtocolMgr protocol, ILogger logger, GiftInfo gift)
        {
            string url = "/root/newGift!getNewGiftReward.action";
            string data = String.Format("giftId={0}", gift.id);
            ServerResult result = protocol.postXml(url, data, "领取玩家礼包");
            if (result == null || !result.CmdSucceed) return;
            XmlDocument xml = result.CmdResult;
            //<results><state>1</state><content>tickets:12000</content></results>
            string desc = String.Format("领取玩家礼包[{0}], 获得[{1}]", gift.name, gift.getContentDesc());
            logInfo(logger, desc);
        }
        private bool getFreeToken(ProtocolMgr protocol, ILogger logger, out int token_remains, out int get_token_cd)
        {
            get_token_cd = 0;
            token_remains = 0;
            string url = "/root/secretary!applyToken.action";
            ServerResult result = protocol.getXml(url, "小秘书领取军令");
            if (result == null || !result.CmdSucceed) return false;
            XmlDocument xml = result.CmdResult;

            int totalToken = 4;
            XmlNode node = xml.SelectSingleNode("/results/maxtokennum");
            if (node != null) Int32.TryParse(node.InnerText, out totalToken);
            int gotToken = 4;
            node = xml.SelectSingleNode("/results/tokennum");
            if (node != null) Int32.TryParse(node.InnerText, out gotToken);
            token_remains = totalToken - gotToken;
           
            node = xml.SelectSingleNode("/results/cd");
            if (node != null) Int32.TryParse(node.InnerText, out get_token_cd);

            logInfo(logger, String.Format("小秘书领取军令, 还剩{0}个", token_remains));
            return true;
        }
        private bool harvestFood(ProtocolMgr protocol, ILogger logger)
        {
            string url = "/root/world!impose.action";
            ServerResult result = protocol.postXml(url, "resId=10", "收取军团农场");
            if (result == null || !result.CmdSucceed) return false;
            XmlDocument xml = result.CmdResult;
            int food_got = 0;
            XmlNode node = xml.SelectSingleNode("/results/gains");
            if (node != null) Int32.TryParse(node.InnerText, out food_got);
            if (food_got == 0) return false;
            logInfo(logger, "收取军团农场, 获得银币 +" + food_got);
            return true;
        }
        private bool harvestStone(ProtocolMgr protocol, ILogger logger)
        {
            string url = "/root/bowlderRes!HarvestNationBowlderRes.action";
            ServerResult result = protocol.getXml(url, "收取国家玉石矿");
            if (result == null || !result.CmdSucceed) return false;
            XmlDocument xml = result.CmdResult;
            XmlNode stone_node = xml.SelectSingleNode("/results/bowlderadd");
            if (stone_node != null)
            {
                int stone_got = Int32.Parse(stone_node.InnerText);
                logInfo(logger, "收取国家玉石矿, 获得原石 +" + stone_got);
                if (stone_got == 0) return false;
            }
            return true;
        }
        #endregion

        #region treasure box
        public void handleNationTreasureInfo(ProtocolMgr protocol, ILogger logger, int box_reserve=450)
        {
            string url = "/root/world!getNewAreaTreasureInfo.action";
            ServerResult result = protocol.getXml(url, "查看国家宝箱");
            if (result == null || !result.CmdSucceed) return;
            XmlDocument xml = result.CmdResult;
            XmlNode node = xml.SelectSingleNode("/results/treasurenum");
            if (node == null) return;
            int treasure_count = 0;
            Int32.TryParse(node.InnerText, out treasure_count);
            if (treasure_count >= box_reserve) openNationTreasure(protocol, logger);
        }
        public void openNationTreasure(ProtocolMgr protocol, ILogger logger)
        {
            string url = "/root/world!draw5NewAreaTreasure.action";
            string desc = "打开国家宝箱*5";
            ServerResult result = protocol.getXml(url, desc);
            if (result == null || !result.CmdSucceed) return;
            XmlDocument xml = result.CmdResult;
            XmlNodeList nodes = xml.SelectNodes("/results/reward");
            int silver_num = 0, token_num = 0, att_token_num = 0, stone_num = 0, treasure_num = 0;
            foreach (XmlNode node in nodes)
            {
                XmlNodeList childs = node.ChildNodes;
                int type = 0, count = 0, tcount = 0;
                foreach (XmlNode child in childs)
                {
                    if (child.Name == "rewardtype") Int32.TryParse(child.InnerText, out type);
                    else if (child.Name == "rewardvalue") Int32.TryParse(child.InnerText, out count);
                    else if (child.Name == "baowu") Int32.TryParse(child.InnerText, out tcount);
                }
                if (type == 1) silver_num += count;
                else if (type == 2) att_token_num += count;
                else if (type == 3) token_num += count;
                else if (type == 4) stone_num += count;
                if (tcount > 0) treasure_num += tcount;
            }
            desc += ", 获得奖励: ";
            if (silver_num > 0) desc += String.Format("银币+{0} ", silver_num);
            if (token_num > 0) desc += String.Format("军令+{0} ", token_num);
            if (att_token_num > 0) desc += String.Format("攻击令+{0} ", att_token_num);
            if (stone_num > 0) desc += String.Format("玉石+{0} ", stone_num);
            if (treasure_num > 0) desc += String.Format("宝物+{0} ", treasure_num);

            logInfo(logger, desc);
        }
        #endregion

        #region daily event
        /// <summary>
        /// 0=success, 1=http failure, 2=get salary failed, 10=other
        /// </summary>
        /// <param name="protocol"></param>
        /// <param name="logger"></param>
        /// <returns></returns>
        public int handleDailyEventInfo(ProtocolMgr protocol, ILogger logger)
        {
            string url = "/root/event.action";
            com.lover.astd.common.model.ServerResult result = protocol.getXml(url, "获取玩家日常事件信息");
            if (result == null) return 1;
            if (!result.CmdSucceed) return 10;
            XmlDocument xml = result.CmdResult;
            XmlNode results = xml.SelectSingleNode("/results/curreventdto");
            XmlNodeList childs = results.ChildNodes;
            int eventId = 0, _salary = 0; long _cd = 0;
            foreach (XmlNode child in childs)
            {
                if (child.Name == "id") eventId = Int32.Parse(child.InnerText);
                else if (child.Name == "cd") Int64.TryParse(child.InnerText, out _cd);
                else if (child.Name == "salary") _salary = Int32.Parse(child.InnerText);
            }
            if (_cd == 0 && _salary > 0)
            {
                bool suc = getEventAward(protocol, logger);
                if (!suc) return 10;
            }
            return 0;
        }
        private bool getEventAward(ProtocolMgr protocol, ILogger logger)
        {
            string url = "/root/event!saveSalary.action";
            com.lover.astd.common.model.ServerResult result = protocol.getXml(url, "获取玩家日常事件奖励");
            if (result == null || !result.CmdSucceed) return false;
            XmlDocument xml = result.CmdResult;
            string salary = xml.SelectSingleNode("/results/salary").InnerText;
            logInfo(logger, String.Format("领取日常事件奖励 {0}银币", salary));
            return true;
        }
        #endregion

        #region ticket auto
        #endregion
    }
}
